在 kotlin 字符串中像 \u... 一样转义十六进制

Escape hex like \u... in kotlin strings

我有一个字符串"\ufffd\ufffd hello\n"

我有这样的代码

    fun main() {
      val bs = "\ufffd\ufffd hello\n"
      println(bs) // �� hello
    }

我想看看 "\ufffd\ufffd hello",我如何为每个十六进制值转义 \u

更新:

val s = """\uffcd"""
val req = """(?<!\\)(\\\\)*(\u)([A-Fa-f\d]{4})""".toRegex()
return s.replace(unicodeRegex, """\\u""")

通过在其前面添加另一个反斜杠,简单地转义字符串中的 \

val bs = "\ufffd\ufffd hello\n"

您还可以将原始字符串与 """ 一起使用,这样您就不必转义反斜杠(这对正则表达式很有用):

val bs = """\ufffd\ufffd hello\n"""

请注意,在这种情况下,\n 也不会被算作 LF 字符,并且会按字面意思打印为 2 个字符“\n”。 如果你想要一个实际的换行符,你可以在你的原始字符串中添加文字换行符,但是:

val bs = """\ufffd\ufffd hello
"""

(我将这个问题解释为询问如何清楚地显示包含不可打印字符的字符串。‖ Kotlin 编译器将 \u 后跟字符串文字中的 4 个十六进制数字的序列转换为单个字符,所以问题实际上是在询问如何将它们再次转换回来。)

不幸的是,没有内置的方法来执行此操作。写一个相当容易,但有点主观,因为没有关于什么是“可打印”的单一定义......

这是一个扩展函数,它可能大致满足您的需求:

fun String.printable() = map {
    when (Character.getType(it).toByte()) {
        Character.CONTROL, Character.FORMAT, Character.PRIVATE_USE,
        Character.SURROGATE, Character.UNASSIGNED, Character.OTHER_SYMBOL
            -> "\u%04x".format(it.toInt())
        else -> it.toString()
    }
}.joinToString("")

println("\ufffd\ufffd hello\n".printable()) // prints ‘\ufffd\ufffd hello\u000a’

问题中的示例字符串是一个不好的例子,因为 \uFFFDreplacement character — 带有问号的黑色菱形,通常显示在任何不可显示的字符的位置。所以替换字符本身 可显示的!

上面的代码通过排除 Character.OTHER_SYMBOL 类型将其视为不可显示——但这也会排除许多其他符号。所以你可能想要删除它,只留下其他 5 种类型。 (我从 this answer 那里得到的。)

因为尾随的换行符是不可显示的,所以它也被转换为十六进制代码。如果需要,您可以扩展代码以处理转义码 \t\b\n\r\。 (你也可以让它更有效率......这样做是为了简洁!)