Java:PHP的ord()的实现会产生超出ASCII

时间:2017-04-18 21:18:23

标签: java php character-encoding

我正在尝试编写与PHP的ord()

等效的Java
public static int ord(char c) {
    return (int) c;
}

public static int ord(String s) {
    return s.length() > 0 ? ord(s.charAt(0)) : 0;
}

这似乎适用于序数值高达127的字符,即ASCII内。但是,对于扩展ASCII表或更高版本的字符,PHP返回195(和更高)。 Mr. Llamathe answer on a related question的评论解释如下:

  

详细说明,原因é显示ASCII 195是因为它实际上是一个双字节字符(UTF-8),其第一个字节是ASCII 195. - Llama先生

因此我改变了我的ord(char c)方法来屏蔽掉除最重要字节之外的所有字节:

public static int ord(char c) {
    return (int) (c & 0xFF);
}

然而,结果不同。两个例子:

  • ord('é')(U + 00E9)在PHP中提供195,而我的Java函数产生233
  • ord('⸆')(U + 2E06)在PHP中提供226,而我的Java函数产生6

我通过首先将String转换为String数组,显式地使用UTF-来接受byte 的方法,以获得相同的行为 8编码:

public static int ord(String s) {
    return s.length() > 0 ? ord((char)s.getBytes(StandardCharsets.UTF_8)[0]) : 0;
}

但是,使用接受char的方法仍然像以前一样,我还无法找到解决方案。另外,我不明白为什么更改确实有效:Charset.defaultCharset()无论如何都会在我的平台上返回UTF-8。所以......

  • 如何使我的功能与PHP的功能类似?
  • 为什么对ord(String s)的更改确实有效?

非常感谢解释性答案,因为我想要了解究竟发生了什么。

1 个答案:

答案 0 :(得分:3)

在Java中char is a UTF-16 code unit。将UTF-16转换为UTF-8不仅仅是& 0xFF,例如UTF-16中的01FF在UTF-8中是C7 BF,因此PHP ord()应该给{ {1}}(199),但0xC7为255。

0x01FF & 0xFF版本有效,因为它实际上正在转换为UTF-8。

最简单的方法是反转你的两个重载,因为String有一个方便的方法来获取UTF-8:

String

convert the char to a String

public static int ord(String s) {
    return s.length() > 0 ? (s.getBytes(StandardCharsets.UTF_8)[0] & 0xff) : 0;
}

虽然这有效,但由于不必要的char→String→int转换,它效率不高。可以使用以下命令实际找到Unicode代码点public static int ord(char c) { return c < 0x80 ? c : ord(Character.toString(c)) } 的UTF-8编码的第一个字节:

c

您可能还想阅读What is Unicode, UTF-8, UTF-16?以获取一些背景信息。