Java String.codePointAt返回意外值

时间:2010-10-16 12:25:24

标签: java string encoding

如果我使用33到127之间的任何ASCII字符,codePointAt方法会给出正确的十进制值,例如:

String s1 = new String("#");
int val = s1.codePointAt(0);

这将返回35,这是正确的值。

但是,如果我尝试使用128到255之间的ASCII字符(扩展ASCII / ISO-8859-1),则此方法会给出错误的值,例如:

String s1 = new String("ƒ")  // Latin small letter f with hook
int val = s1.codePointAt(0);

这应该按照this reference table返回159,而是返回409,为什么会这样?

4 个答案:

答案 0 :(得分:5)

  

但是,如果我尝试使用128到255的ASCII字符

ASCII没有此范围内的值。它只使用7位。

Java字符是UTF-16(没有别的!)。如果要使用Java表示ASCII,则需要使用字节数组。

codePointAt方法返回32位代码点。 16位字符不能包含整个Unicode范围,因此某些代码点必须分成两个字符(根据encoding scheme for UTF-16)。 codePointAt方法有助于解决代码点的问题。

我在Java here中写了一个粗略的编码指南。

答案 1 :(得分:2)

Java字符未在ISO-8859-1中编码。它们使用UTF-16,它具有7bit ASCII字符的相同值(仅0-127的值)。

要获得ISO-8859-1的正确值,您必须使用 String.getBytes("ISO-8859-1"); 将字符串转换为byte []并查看字节数组。

<强>更新

ISO-8859-1不是extended ASCII编码,使用String.getBytes("Cp437");来获取正确的值。

答案 2 :(得分:0)

Unicode中的

ƒ 0x0192 LATIN SMALL LETTER F WITH HOOK

答案 3 :(得分:0)

String.codePointAt返回此指定索引处的Unicode-Codepoint。

ƒ的Unicode代码点是402,参见

http://www.decodeunicode.org/de/u+0192/properties

所以

System.out.println("ƒ".codePointAt(0));

打印402是正确的。

如果您对其他字符集中的表示感兴趣,可以通过getBytes(String charsetName)打印出其他字符集中字符的字节表示:

    final String s = "ƒ";
    for (final String csName : Charset.availableCharsets().keySet()) {
    try {
     final Charset cs = Charset.forName(csName);
     final CharsetEncoder encode = cs.newEncoder();
     if (encode.canEncode(s)) 
          {
      System.out.println(csName + ": " + Arrays.toString(s.getBytes(csName)));
          }
        } catch (final UnsupportedOperationException uoe) {
        } catch (final UnsupportedEncodingException e) {
     }
    }