私は 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 つの文字セットに関する私の (非常に基本的な!) 理解から、1 文字を読み取るのに必要な正確なバイト数をいつでも特定できるため、先読みは必要ありません。
背景は、さまざまなエンコーディング (数値、文字列、1 バイト トークンなど) のデータの束を含むバイナリ ファイルがあったことです。基本的な形式は、バイト マーカー (データのタイプを示す) の繰り返しセットで、その後に必要に応じてそのタイプにオプションのデータが続きます。文字データを含む 2 つの型は、NULL で終了する文字列と、前に 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 バッファリングの問題を見てきましたが、この特定の質問には答えていないようです。
乾杯、