Java:PHP 的 ord() 的实现对 ASCII 以外的字符产生不同的结果
Posted
技术标签:
【中文标题】Java:PHP 的 ord() 的实现对 ASCII 以外的字符产生不同的结果【英文标题】:Java: Implementation of PHP's ord() yields different results for chars beyond ASCII 【发布时间】:2017-09-14 21:27:44 【问题描述】:我正在尝试编写与 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. Llama 到 the answer on a related question 的评论解释如下:
详细来说,é 显示 ASCII 195 的原因是因为它实际上是一个两字节字符 (UTF-8),其中第一个字节是 ASCII 195。——骆驼先生
因此,我更改了我的 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
转换为 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
。所以……
ord(String s)
确实有效?
非常感谢您提供解释性答案,因为我想准确了解发生了什么。
【问题讨论】:
Java 似乎是正确的; 233 确实是é
的代码:ascii-code.com。 195 是Ã
的代码,所以谁知道 WTF 在 PHP 的幕后工作。
其实好像和这个有很大关系:***.com/questions/35575721/ord-doesnt-work-with-utf-8
@OliverCharlesworth 是正确的,PHP 的 ord()
不能正确处理 ASCII 范围之外的字符。但是,我正在尝试复制这种行为。
【参考方案1】:
在 Java 中为 char
is a UTF-16 code unit。将 UTF-16 转换为 UTF-8 不只是 & 0xFF
,例如 UTF-16 中的 01FF
是 UTF-8 中的 C7 BF
,所以 PHP 的 ord()
应该给出 0xC7
(199),但 @ 987654330@ 是 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 大约 3 年了,从不知道它在内部使用了 UTF-16。我会确保仔细阅读链接的参考资料。以上是关于Java:PHP 的 ord() 的实现对 ASCII 以外的字符产生不同的结果的主要内容,如果未能解决你的问题,请参考以下文章
sql 第2行显示如何GROUP BY Last Name,然后ORDER BY两件事 - 首先是COUNT(OrderID),然后是LastName,在ASC ord中排序
基于流式输入输出 使用Java借助GSON库 实现对大型asc文件的读入解析 并输出为JSON文件
基于流式输入输出 使用Java借助GSON库 实现对大型asc文件的读入解析 并输出为JSON文件