我正在尝试编写一个相当于PHP的EDCOX1第0章的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(及更高版本)。Llama先生对相关问题的答案的评论解释如下:
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+0E9)在PHP中给出EDCOX1,2,而我的Java函数产生EDCOX1〔6〕。
ord('?')(U+2E06)在PHP中给出EDCOX1,8,而我的Java函数产生EDCOX1〔9〕。
我试图通过首先将String转换为byte数组(显式使用utf-8编码)来获得接受String的方法的相同行为:
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似乎是正确的;233确实是EDCOX1的代码0个:ASCII CODEM.195是Ã的代码,所以谁知道wtf是在php中进行的。
事实上,似乎与此密切相关:stackoverflow.com/questions/35575721/ord不适用于ut‌&諾8203;f-8
@OliverCharlesworth是正确的,PHP的ord()不能正确地处理ASCII范围之外的字符。然而,我正试图复制这种行为。
在爪哇中,EDCOX1×0是UTF 16编码单元。将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;
}
将char转换为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;
}
您可能还想读取什么是unicode、utf-8、utf-16?获取一些背景信息。
啊,这解释了一切!回答很好,谢谢。我现在使用Java大约3年了,从来没有知道它在内部使用UTF16。我会仔细阅读链接的参考资料。