我从 InputStreamReader 开始,但这缓冲了它的输入,从输入流中读取的内容超过了所需的内容(如其 Java 文档中所述)。深入研究源代码(java 版本“1.7.0_147-icedtea”),我找到了 sun.nio.cs.StreamDecoder 类,其中包含以下注释:
// In order to handle surrogates properly we must never try to produce
// fewer than two characters at a time. If we're only asked to return one
// character then the other is saved here to be returned later.
所以我想问题变成了“这是真的吗,如果是,为什么?” 根据我(非常基本!)对 JLS 所需的 6 个字符集的理解,始终可以确定读取单个字符所需的确切字节数,因此无需预读。
背景是我有一个二进制文件,其中包含一堆具有不同编码(数字、字符串、单字节标记等)的数据。基本格式是一组重复的字节标记(指示数据类型),如果该类型需要,则后跟可选数据。包含字符数据的两种类型是以空字符结尾的字符串和前一个 2 字节长度的字符串。因此,对于以空结尾的字符串,我认为这样的事情可以解决问题:
String readStringWithNull(InputStream in) throws IOException {
StringWriter sw = new StringWriter();
InputStreamReader isr = new InputStreamReader(in, "UTF-16LE");
for (int i; (i = isr.read()) > 0; ) {
sw.write(i);
}
return sw.toString();
}
但是 InputStreamReader 从缓冲区中提前读取,因此对基本 InputStream 的后续读取操作丢失了数据。对于我的特殊情况,我知道所有字符都是 UTF-16LE BMP(有点像 UCS-2LE),所以我只是围绕它进行编码,但我仍然对上述一般情况感兴趣。
另外,我看到了类似的InputStreamReader 缓冲问题,但似乎没有回答这个特定问题。
干杯,