java - 在Java中,使用从InputStream.read()返回的int来调用Character.isXxx()方法是否安全?

标签 java unicode character inputstream

当读取文本文件时,我想做这样的事情:

InputStream input = ...;
int read = input.read();
if (Character.isWhitespace(read)) {
    // do something with the whitespace
}

另一种方法是检查负的 read() 返回值(也称为输入结束)并显式强制转换:

InputStream input = ...;
int read = input.read();
if (read >= 0 && Character.isWhitespace((char) read)) {
    // do something with the whitespace
}

但是,这涉及额外的分支和转换,并且我希望我的代码尽可能高效,因此我更喜欢第一种方法。

但是,我希望我的代码更加健壮:),并且我不确定第一种方法是否会产生微妙的问题。根据我收集的信息,Unicode 将 0xFFFF0xFFFFFFFF 定义为非字符,所以我认为它是安全的。但专家们怎么说呢?

为了确保,问题涉及我的方法是否对所有 Character.isXxx() 方法都安全,而不仅仅是 Character.isWhitespace() .

最佳答案

InputStream.read() 方法读取单个 8 位字节,并将其作为范围内的 32 位 int 返回0x00 - 0xFF,或在 EOF 时返回 -1

接受 32 位 int 作为输入的 Character.isXXX() 方法需要 完整 Unicode 代码点,范围为 0x00 - 0x10FFFF。如果文件由 7 位 ASCII 字符组成(其中字节 0x00 - 0x7F 映射到代码点 U+,则单个字节可能按原样表示完整的代码点0000 - U+007F),或 ISO-8859-1(其中字节 0x00 - 0xFF 映射到代码点 U+0000 - U+00FF)。如果文件使用任何其他编码,则无法保证任何给定字节将按原样映射到相同值的代码点,特别是当该字节大于0x7F(大多数 7/8 位编码使用相同的字节值来实现 ASCII 兼容性 - 但并非全部如此!)。

接受 16 位 char 作为输入的 Character.isXXX() 方法需要 UTF-16 codeunit 在以下范围内: 0x00 - 0xFFFF。单个 char 可以按原样保存 Unicode 代码点,最高可达代码点 U+FFFF。但是,这些方法支持 UTF-16 代理,因此无法处理高于 U+FFFF 的 Unicode 代码点(需要 2 个 char 值来处理)代表他们)。

所以,为了回答你的问题 - 你可以read()从文件中读取任何给定的字节并将其按原样传递给Character.isXXX()方法并得到可靠的结果?答案是 - 这取决于文件的实际编码。如果文件以 7 位 ASCII 或 8 位 ISO-8859-1 编码,则可以。否则,也许,但通常仅适用于字节 0x7F,因为字节 0x80 - 0xFF 是特定于编码的,并且取决于特定编码在字节和 Unicode 代码点之间的映射方式(假设该文件甚至开始使用 7/8 位编码)。

关于java - 在Java中,使用从InputStream.read()返回的int来调用Character.isXxx()方法是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28795211/

相关文章:

css - 半个单词、句子等的样式

c - 为什么第一次输入后字符计数错误?

java - 如何在 NetBeans 的对话框中显示 JTable?

java - 使用祖 parent 接口(interface)的默认方法

python - 格式化包含非 ascii 字符的列

java - Java 中的重读文字

ubuntu - 为什么ubuntu 16.04无法使用搜狗拼音输入法输入汉字?

java - BufferedReader 的 JRE6 兼容性问题

Java swing - 频繁改变框架的颜色

python - 为什么我会收到错误 "TypeError: coercing to Unicode: need string or buffer, int found"?