我正在尝试编写一个与 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 内。但是,PHP 返回 195
(及更高)适用于扩展 ASCII 表或其他表中的字符。 Mr. Llama 的评论至 the answer on a related question解释如下:
To elaborate, the reason é showed ASCII 195 is because it's actually a two-byte character (UTF-8), the first byte of which is ASCII 195. – Mr. Llama
因此我改变了我的ord(char c)
屏蔽除最高有效字节之外的所有字节的方法:
public static int ord(char c) {
return (int) (c & 0xFF);
}
尽管如此,结果还是有所不同。两个例子:
-
ord('é')
(U+00E9) 给出195
在 PHP 中,而我的 Java 函数产生233
-
ord('⸆')
(U+2E06) 给出226
在 PHP 中,而我的 Java 函数产生6
对于接受 String
的方法,我设法获得相同的行为 首先转动String
进入byte
数组,显式使用 UTF-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)
真的有效吗?
非常感谢解释性答案,因为我想准确了解到底发生了什么。
最佳答案
在 Java 中 char
is a UTF-16 code unit 。将UTF-16转换为UTF-8不仅仅是&0xFF
,例如UTF-16中的01FF
在UTF-8中是C7 BF
,因此 PHP ord()
应该给出 0xC7
(199),而 0x01FF & 0xFF
则是 255。
String
版本可以工作,因为它实际上正在转换为 UTF-8。
最简单的方法是反转两个重载,因为 String
有一个方便的方法来获取 UTF-8:
public static int ord(String s) {
return s.length() > 0 ? (s.getBytes(StandardCharsets.UTF_8)[0] & 0xff) : 0;
}
和convert the char
to a String
:
public static int ord(char c) {
return c < 0x80 ? c : ord(Character.toString(c))
}
虽然这有效,但由于不必要的 char→String→int 转换,效率不高。 Unicode 代码点 c
的 UTF-8 编码的第一个字节实际上可以使用以下命令找到:
if (c < 0x80) {
return c;
} else if (c < 0x800) {
return 0xc0 | c >> 6;
} else if (c < 0x10000) {
return 0xe0 | c >> 12;
} else {
return 0xf0 | c >> 18;
}
您可能还想阅读What is Unicode, UTF-8, UTF-16?了解一些背景信息。
关于Java:PHP 的 ord() 的实现对于 ASCII 之外的字符产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43482364/