单个中文字符在Java / Scala字符串中确定为长度2

时间:2015-02-27 09:19:36

标签: java scala character-encoding

我试图从字符串中分割出所有中文字符,但我遇到了一个奇怪的角色情况

scala> ""
res1: String = 

scala> res1.length
res2: Int = 2

scala> res1.getBytes
res3: Array[Byte] = Array(-16, -91, -111, -82)

scala> res1(0)
res4: Char = ?

scala> res1(1)
res5: Char = ?

它是一个单个字符,但Java / Scala将其确定为两个未知字符。通常我看到中文字符在UTF-8中占用三个字节,但这个字符需要四个字节。

因此,我无法拆分字符串并找到这个单字符。更糟糕的是,当使用myString.replaceAll("[^\\p{script=Han}]", "")踢出所有非中文字符时,第二部分被替换,它变成无效的字符串。

这有什么解决方案吗?我在Ubuntu上使用openjdk-8-jdk。

6 个答案:

答案 0 :(得分:8)

如果长度你应该使用

string.codePointCount(0, string.length());

对于替换,最好避免使用基于字符的正则表达式。您可以根据String#offsetByCodePoints()编写一个循环,并根据String.codePointAt()Character.isIdeographic()手动删除字符。

答案 1 :(得分:3)

您遇到了代理对。该字符为U+2546E,如您所见,比2 ^ 16大很多。它在Java或Scala字符串中表示为序列0xD855 0xDC6E。

如果你想要一个透明地处理这类事情的正则表达式库,我碰巧知道在哪里找到一个:TCL regex ported to Java。如果你不想去那里,你需要使用java中String和Character的Code Point方法进行导航。

答案 2 :(得分:1)

Java标准库unicode支持早于当前标准,因此对星体(非BMP)字符的支持是有限的;如您所见,几个API会将它们视为单独的代理对。如果你正在进行大量的字符串操作,最好使用ICU4J,我理解它提供完全unicode支持的正则表达式。

答案 3 :(得分:0)

基于@Marko的回答,这是一个分割字符串的例子:

scala> val x = "硓abc"
x: String = 硓abc

scala> (0 to x.codePointCount(0, x.length)).map(c => x.offsetByCodePoints(0, c)).sliding(2).map(w => x.substring(w.head, w.last)).toList
res1: List[String] = List(硓, , a, b, c)

并确定每个角色是否为CJKV:

scala> (0 until x.codePointCount(0, x.length)).map(c => x.offsetByCodePoints(0, c)).map(i => Character.isIdeographic(x.codePointAt(i))).toList
res2: List[Boolean] = List(true, true, false, false, false)

答案 4 :(得分:-2)

我认为你想要替换/拆分字符串。你可以在不知道字符串长度的情况下做。因为java也需要字符串序列来替换字符串中特定的char或char序列。例如:-`public class Test {

public static void main(String[] args) {


    String s="";
    System.out.println(s.replace("", "k"));

}
}

` 如果你想拆分String,那就去找stringtokenizer。例如: -

StringTokenizer st= new StringTokenizer("your sentence or String","the problematic char/string");

答案 5 :(得分:-3)

可能此字符在UTF-8中无效或不受支持但在UTF-16中受支持,导致JVM和Scala shell之间存在某些不兼容性。你的系统是大端还是小端?您也可以尝试获取角色的Unicode代码点,并检查它是UTF-8还是UTF-16。此外,中文复杂的字母,如日语汉字和Furigana,所以这也可能是你问题的一部分。