Rap*_*ita 1 java string contains character-encoding kotlin
我在使用不同编码器比较两个字符串时遇到了问题。我的代码实际上是用 Kotlin 编写的,但它在 JVM 上运行,并且有效地使用了 Java 的 String 实现。另外,我的问题具有更普遍的性质,我的实际代码不会受到关注。
\n问题是我有两个字符串,比如说a和b,其中
a = "something something \xc3\xa4\xc3\xb6\xc3\xbc something"\nb = "\xc3\xa4\xc3\xb6\xc3\xbc"\nRun Code Online (Sandbox Code Playgroud)\n您期望a.contains(b)返回true,如果您像上面所示检索字符串,情况就是如此。但就我而言,字符串来自不同的来源,并且碰巧有不同的编码器。Stringa有编码器1,即UTF16,并且 Stringb有编码器0,即LATIN1。在这种情况下,a.contains(b)返回 false。现在您可能已经注意到我包含了特殊字符(\xc3\xa4、\xc3\xb6和\xc3\xbc),因为根据我的调试,这就是比较失败的地方。
当我位于a.contains(b)发生调用的堆栈帧时,两个字符串都正确显示在我的调试器 (IntelliJ IDEA Ultimate 2020.2) 中。但是,如果我随后进入比较函数,我注意到在java.lang.StringLatin1.regionMatchesCI_UTF16()字节数组逐字符转换回的位置,特殊字符b现在不正确(\xc3\xa4-> a、\xc3\xb6-> o、\xc3\xbc-> u)。当然,这样比较就失败了。
现在正如我所说,两个字符串最初都在调试器中正确显示,因此信息必须位于某处。我的问题是:我必须做什么才能让呼叫按预期a.contains(b)返回?true
编辑:
\n我确信问题源于具有两个不同编码器的字符串。然而,即使不同的编码者暗示不同的编码在起作用,但这并不是问题的根源。.equals()一般来说,不同的编码器不会影响、.contains()或类似调用的结果。@OrangeDog 指出了这一点,同时也暗示我实际上最终得到了同一个角色的两种不同表示,事实确实如此。尽管如此,我的问题仍然是一样的:如何比较这两个“语义”相同但某些字符的表示不同的字符串?
忽略内部细节String。就您而言,它没有编码,它只存储字符序列(或 Kotlin 文档所描述的“代码点单元”)。
我猜你的一个字符串(即 Latin-1)使用字符U+00E4(\xc3\xa4),另一个使用序列U+0061 U+0308(a\xcc\x88)。您可以使用 进行验证toCharArray()。
为了能够明智地比较这些字符串,有这样的类java.text.Normalizer:
Normalizer.normalize(a, Form.NFKD).contains(Normalizer.normalize(b, Form.NFKD))\nRun Code Online (Sandbox Code Playgroud)\n或者,确保您收到的任何字符串均已采用推荐的NFC形式。
| 归档时间: |
|
| 查看次数: |
1571 次 |
| 最近记录: |