pab*_*iva 20 java string unicode
让我们假设我们想要恢复以下字符串"áe".
这个unicode是"\ u0061\u0301\u0065".
恢复它的天真的方法将是char的char
private static String reverseStringNaive(String s) {
char[] characters = new char[s.length()];
for (int i = s.length() - 1; i >= 0; i--) {
int j = s.length() - i - 1;
characters[j] = s.charAt(i);
}
return new String(characters);
}
Run Code Online (Sandbox Code Playgroud)
当我们希望获得"eá"(\ u0065\u0061\u0301)时,它给了我们"éa"(\ u0065\u0301\u0061).精确的"'"应该与"a"结合在一起,而不是改为"e".
以下代码为我提供了该String的预期结果:
private static String reverseString(String s) {
char[] characters = new char[s.length()];
for (int i = s.length() - 1; i >= 0; i--) {
int j = s.length() - i - 1;
if (Character.isLetterOrDigit(s.charAt(i)) || Character.isISOControl(s.charAt(i))) {
characters[j] = s.charAt(i);
} else {
characters[j] = s.charAt(i-1);
characters[j+1] = s.charAt(i);
i--;
}
}
return new String(characters);
}
Run Code Online (Sandbox Code Playgroud)
我正在检查每个字符是否为Letter,Digit或ISO Control.如果没有,我认为它应该与前一个角色保持一致.
问题是,还有其他我应该检查或担心的事情吗?我的aproach仍然天真吗?
您的问题也可以通过将字符串转换为规范的分解形式 NFC 来解决。基本上,java.text.Normalizer 类可用于将重音符号和其他组合字符与其基本字符组合起来,以便您能够正确地反转。
\n\n所有这些其他想法(String.reverse()、StringBuffer.reverse())都将正确反转缓冲区中的字符,但如果您从分解的字符开始,您可能不会得到您所期望的:)。
\n\n在某些“分解形式”中,重音字符与其基本形式分开存储(作为单独的字符),但在“组合”形式中则不是。因此,在一种形式中,“\xc3\xa1e”存储为三个字符,而在另一种组合形式中,存储为两个字符。
\n\n然而,这种规范化不足以处理其他类型的字符组合,也不能解释 Unicode 星体平面中的字符,这些字符在 Java 中存储为两个字符(或更多?)。
\n\n感谢 tchrist 指出 ICU 对文本分割的支持,包括扩展的字素簇,例如下面评论中指出的(请参阅 virama)。 该资源似乎是此类内容的权威信息来源。
\n