在阅读文本文件时,我想做这样的事情:
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()
。
答案 0 :(得分:2)
InputStream.read()
方法读取单个8位字节并将其作为int
范围内的32位0x00 - 0xFF
返回,或者返回{ EOF上的{1}}。
接受32位-1
作为输入的Character.isXXX()
方法需要{strong>完整的Unicode代码点,范围为int
。如果文件由7位ASCII字符组成(其中字节0x00 - 0x10FFFF
映射到代码点0x00 - 0x7F
)或ISO-,则单个字节可以按原样表示完整代码点8859-1(其中字节U+0000 - U+007F
映射到代码点0x00 - 0xFF
)。如果文件使用任何其他编码,则无法保证任何给定字节将按原样映射到具有相同值的代码点,尤其是当字节大于U+0000 - U+00FF
时(大多数7/8位编码使用相同的字节值进行ASCII兼容 - 但不是全部都这样做。)。
接受16位0x7F
作为输入的Character.isXXX()
方法需要{strong> UTF-16代码单元,范围为char
。单个0x00 - 0xFFFF
可以保存Unicode代码点,直到代码点char
。但是,这些方法不支持支持UTF-16代理,因此无法处理U+FFFF
上方的Unicode代码点(需要2 U+FFFF
个值来代表它们)。
因此,要回答您的问题 - 您可以char
来自文件的任何给定字节并将其原样传递给read()
方法并获得可靠的结果吗?答案是 - 取决于文件的实际编码。如果文件是以7位ASCII或8位ISO-8859-1编码,那么是。否则,可能是,但通常仅用于字节0x7F,因为字节Character.isXXX()
是特定于编码的,并且将取决于特定编码如何在字节和Unicode代码点之间映射(假设文件甚至使用一个7/8位编码开始)。
答案 1 :(得分:0)
是的,这很安全。对于0xFFFFFFFF
情况,所有isXxx方法都返回false。实际上,对于0x000FFFFF
之外的所有内容都是如此,因为这些值在Unicode中是未定义的。对于0xFFFF
,它大致相同,尽管isBmpCodePoint
是真的。