4

ここに明らかな何かが欠けている場合は申し訳ありません...しかし、このコードスニペットを見てください:

String readString;
String writeString = "O hai world.";
BufferedReader br = new BufferedReader(
    new InputStreamReader( 
        new ByteArrayInputStream(writeString.getBytes()),
        "UTF-8"),
    1024);
readString = br.readLine();
System.out.println("readString: " + readString);

有効な EOL を検出する前に BufferedReader が EOF に遭遇すると思っていたので、これは "readString: null" を出力すると予想していましたが、代わりに "readString: O hai world" を出力しました。これは、 BufferedReader の Javadocs が readLine() が行うと言っていることとは反対のようです。

1 行のテキストを読み取ります。行は、ライン フィード ('\n')、キャリッジ リターン ('\r')、またはキャリッジ リターンの直後のラインフィードのいずれかによって終了すると見なされます。

戻り値: 行終了文字を含まない、行の内容を含む文字列、またはストリームの末尾に到達した場合は null

文字列が '\n' や '\r' で終了するように再解釈される理由がわかりません...誰か教えてください。ありがとう!

編集: いくつかのコンテキストを提供するために、System.in で読み取るように設計された、私が作成した Reader クラスを検証する JUnit テストを作成しようとしています。ByteArrayInputStreams を使用することは、System.in をシミュレートする合理的な方法のように思えました (この関連する SO 投稿を参照してください)。

Reader が行をキャプチャするとき、現在は BufferedReader.readLine() に依存しています。私の目的のために、リーダーの行はすべて「\n」または「\r」で終了している必要があります。EOL なしで EOF に遭遇すると、有効な行に解決されません。したがって、この時点での私の質問は次のとおりだと思います(時間があるときに自分でこれらをさらに詳しくテストしようとしますが、賢い人々が私を助けてくれることを願っています):

  • BufferedReader.readLine() は壊れていますか、文書化されていませんか? または、バイト配列が使い果たされたときに、ByteArrayInputStream は何か間違ったものを返していますか?
  • Reader をテストするこの方法は間違っていますか? また、System.in に対して使用したときに readLine() が正しく機能することを期待する必要がありますか? 私は、これに対する答えは「はい」であると信じたいと思っています。
  • 単体テストのために System.in をシミュレートするより良い方法はありますか?
  • InputStream から読み取るときに '\n' と '\r' を厳密に区別する必要がある場合、独自の readLine() メソッドを作成したほうがよいでしょうか? もしこれが本当なら、私は非常に驚くだろう。

再度、感謝します!

4

5 に答える 5

3

ByteArrayInputStreamは、使い果たされたときにEOLを返しません。EOFと見なされる可能性のある-1のみを返します。

これは、BufferedReaderが入力ストリームから読み取ったすべての文字をバッファリングし、EOL文字が表示される前にEOF(-1)が検出された場合、その時点までにバッファリングされた文字列を返します。

したがって、非常に厳密にしたい場合は、readLine()が現在のドキュメントに従って壊れているか、これが意図された動作である場合は別の方法でドキュメント化する必要があると言うことができます。

私の意見では、ストリームの最後の行がEOL文字で終わる必要はない(EOFで十分)ことを考えると、readLineの現在の動作は正しいです。つまり、EOFが検出されたために行が読み取られました。したがって、ドキュメントを変更する必要があります。

于 2012-07-20T22:02:16.113 に答える
1

これにより、実際のストリーム(ネットワークソケットなど)からの読み取りがブロックされると思います。ただし、基になる入力は配列であるため、リーダーはデータの真の終わりに到達したことを認識します。したがって、新しいデータが来ないため、ブロックは不要です。したがって、ブロックすることは間違った行動方針になります。実際のデータが読み取られた場所でnullを返すことも、間違ったことです。

于 2012-07-20T20:51:20.863 に答える
1

テスト目的で「ロボット」にキーストロークをエミュレートする必要があると思います。

このクラスは、テストの自動化、自己実行デモ、およびマウスとキーボードの制御が必要なその他のアプリケーションのために、ネイティブ システム入力イベントを生成するために使用されます。Robot の主な目的は、Java プラットフォーム実装の自動テストを容易にすることです。

これについてさらに議論する記事は次のとおりです。

于 2012-07-21T16:43:08.490 に答える
0

現在行われていることの唯一の代替手段は、最後の不完全な行を捨てることです。望ましくない。

于 2012-07-21T05:09:15.540 に答える
0

このバージョンのコードで何が起こると思いますか?

String readString;
String writeString = "O\nhai\nworld.";
BufferedReader br = new BufferedReader(
    new InputStreamReader( 
        new ByteArrayInputStream(writeString.getBytes()),
        "UTF-8"),
    1024);
while (true) {
    readString = br.readLine();
    if (readString == null) break;
    System.out.println("readString: " + readString);
}
于 2012-07-20T21:45:18.447 に答える