【问题标题】:Use Unicode in Android在 Android 中使用 Unicode
【发布时间】:2020-11-18 23:23:26
【问题描述】:

在使用 Android 应用程序时,我观察到 Unicode 是 API 响应的一部分:

{
"msg_txt":"Laurent Ruquier et l'\\u00e9quipe"
}

在 Android 端,我有一个简单的TextView,我必须通过将 Unicode 转换为文本来显示实际文本。

【问题讨论】:

  • 无需转换,自动显示unicode后面的文字
  • 是的,但是正如您在上面的 JSON 中看到的那样,它会按原样显示。
  • ok 尝试从 \\ 中删除一个 \
  • 你只有一个转义字符串,而不是一个 unicode 字符串。只是“逃避”它。一个普通的 JSON 阅读器应该可以做到,或者有各种库。

标签: android unicode textview


【解决方案1】:

由于响应中已经包含 unicode 字符,因此您需要对其进行解析。我不是重新发明轮子的朋友,所以你通常会使用像 apache commons unescapeJava 这样的东西。如果您决定将其作为依赖项添加到您的 gradle 构建中,请确保正确配置您的 R8 收缩 (see here),否则您将在发布构建中添加大量方法和类。这也会大大减慢调试构建速度,所以要小心。

虽然上述方法实际上不仅仅是替换转义的 unicode 字符,但如果您只需要此功能并且不想为这段代码添加 apache 依赖项,我们可以查看它们的实现 herehere。我提取了相关部分并将其转换为 Kotlin,只是为了好玩:

val inputString = "Laurent Ruquier et l'\\u00e9quipe"
val unescaped = translate(inputString)


//this is the main method that does the actual conversion on a character
// by character basis.
fun translate(input: CharSequence, index: Int, out: Writer): Int {
    if (input[index] == '\\' && index + 1 < input.length && input[index + 1] == 'u') {
        // consume optional additional 'u' chars
        var i = 2
        while (index + i < input.length && input[index + i] == 'u') {
            i++
        }
        if (index + i < input.length && input[index + i] == '+') {
            i++
        }
        if (index + i + 4 <= input.length) {
            // Get 4 hex digits
            val unicode = input.subSequence(index + i, index + i + 4)
            try {
                val value = unicode.toString().toInt(16)
                out.write(value)
            } catch (nfe: NumberFormatException) {
                throw IllegalArgumentException("Unable to parse unicode value: $unicode", nfe)
            }
            return i + 4
        }
        throw IllegalArgumentException(
            "Less than 4 hex digits in unicode value: '"
                    + input.subSequence(index, input.length)
                    + "' due to end of CharSequence"
        )
    }
    return 0
}

//helper method for working directly with strings
fun translate(input: CharSequence): String {
    val writer = StringWriter(input.length * 2)
    translate(input, writer)
    return writer.toString()
}

// this goes through the actual char sequence and passes every
// single char to the unicode transformer and swallows consumed chars 
fun translate(input: CharSequence, out: Writer) {
    var pos = 0
    val len = input.length
    while (pos < len) {
        val consumed = translate(input, pos, out)
        if (consumed == 0) {
            // inlined implementation of Character.toChars(Character.codePointAt(input, pos))
            // avoids allocating temp char arrays and duplicate checks
            val c1 = input[pos]
            out.write(c1.toInt())
            pos++
            if (Character.isHighSurrogate(c1) && pos < len) {
                val c2 = input[pos]
                if (Character.isLowSurrogate(c2)) {
                    out.write(c2.toInt())
                    pos++
                }
            }
            continue
        }
        // contract with translators is that they have to understand codepoints
        // and they just took care of a surrogate pair
        for (pt in 0 until consumed) {
            pos += Character.charCount(Character.codePointAt(input, pos))
        }
    }
}

请注意,这实际上是简单的框架,可能需要针对实际生产用途进行一些调整。如果例如您的输入将包含两个反斜杠(如val inputString = "Laurent Ruquier et l'\\\\u00e9quipe"),您需要稍微修改一下方法。

【讨论】:

    猜你喜欢
    • 2013-05-23
    • 2018-07-16
    • 2012-12-29
    • 1970-01-01
    • 2012-06-25
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多