当读取文本文件时,我想做这样的事情:
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 将 0xFFFF
和 0xFFFFFFFF
定义为非字符,所以我认为它是安全的。但专家们怎么说呢?
为了确保,问题涉及我的方法是否对所有 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/