BufferedReaderのガイド
1概要
BufferedReader
は、文字入力ストリームからのテキストの読み取りを簡単にするクラスです。
テキストデータの効率的な読み取りを可能にするために文字をバッファします。
このチュートリアルでは、
BufferedReader
クラスの使用方法を見ていきましょう
_.
_
2
BufferedReader
を使用する場合
一般に、
BufferedReader
は、ファイル、ソケット、その他のものなど、あらゆる種類の入力ソースからテキストを読みたい場合に便利です。
簡単に言えば、** 文字の塊を読み込んで内部バッファに格納することで、入出力操作の数を最小限に抑えることができます。
2.1. 他のリーダーのバッファリング
ほとんどのJava I/Oクラスと同様に、
__ BufferedReader
implements
Decoratorパターン、
はコンストラクタ内で
Reader
が必要であることを意味します。
このようにして、
Reader__実装のインスタンスを柔軟に拡張できます。バッファリング機能付き
BufferedReader reader =
new BufferedReader(new FileReader("src/main/resources/input.txt"));
しかし、バッファリングが問題にならない場合は、____FileReaderを直接使用することができます。
FileReader reader =
new FileReader("src/main/resources/input.txt");
バッファリングに加えて、**
__ BufferedReader
alsoは、ファイルを行単位で読み込むための優れたヘルパー関数をいくつか提供します。そのため、
FileReaderを直接使用するほうが簡単に見えるかもしれませんが、
BufferedReader__は大きな助けになります。
2.2. ストリームのバッファリング
一般的に、あらゆる種類の入力ストリームを基になるソースとして扱うように
BufferedReader
を設定することができます。
InputStreamReader
を使用してそれをコンストラクタでラップすることができます。
BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));
上記の例では、通常はキーボードからの入力に対応する
__System.inから読み取ります。同様に、ソケット、ファイル、または考えられるタイプのテキスト入力から読み取るための入力ストリームを渡すことができます。唯一の前提条件は、それに適した
InputStream__実装があることです。
2.3. BufferedReaderとScanner
代わりに、
Scanner
クラスを使用して__BufferedReader.と同じ機能を実現できます。
ただし、これら2つのクラスには大きな違いがあり、ユースケースに応じて、これらのクラスが多少なりとも便利になります。
-
BufferedReader
は同期されていますが(スレッドセーフ)、Scannerは同期していません -
__Scanner
__は通常の方法でプリミティブ型と文字列を解析する
式
**
BufferedReader
はバッファのサイズを変更することを可能にします
スキャナは固定バッファサイズを持っています
**
BufferedReader
のデフォルトバッファサイズが大きくなりました
-
Scanner
は
IOException
を隠し、
BufferedReader
は強制的に
扱う
**
BufferedReader
は通常
Scanner
より速いです。
解析せずにデータを読み取る
これらを念頭に置いて、ファイル内の個々のトークンを解析する場合、
Scanner
は
__BufferedReaderよりも少し自然に感じられます。ただし、一度に1行ずつ読み取るのは、
BufferedReaderが
__輝く場所です。
必要に応じて、https://www.baeldung.com/java-scanner[
Scanner
]のガイドもあります。
3
BufferedReader
でテキストを読む
テキストファイルから読み込むための____BufferReaderの構築、使用、破棄の全プロセスを見ていきましょう。
3.1.
BufferedReader
を初期化する
まず、**
BufferedReader(Reader)
コンストラクタを使って
BufferedReader
を作成しましょう。
BufferedReader reader =
new BufferedReader(new FileReader("src/main/resources/input.txt"));
このように
FileReader
をラップすることは、他の読者にアスペクトとしてバッファリングを追加するための良い方法です。
デフォルトでは、これは8 KBのバッファを使用します。ただし、もっと小さいブロックやもっと大きいブロックをバッファリングする場合は、
BufferedReader(Reader、int)
コンストラクタを使用できます。
BufferedReader reader =
new BufferedReader(new FileReader("src/main/resources/input.txt")), 16384);
これはバッファサイズを16384バイト(16 KB)に設定します。
最適なバッファサイズは、入力ストリームの種類やコードが実行されているハードウェアなどの要因によって異なります。このため、理想的なバッファサイズを実現するには、実験して自分で見つけなければなりません。
ほとんどのハードウェアデバイスはブロックサイズとして2のべき乗を持っているので、バッファサイズとして2のべき乗を使用するのが最善です。
最後に、**
Files
ヘルパークラスを使用して
BufferedReader
を作成するもう1つの便利な方法があります。
java.nio
API:
BufferedReader reader =
Files.newBufferedReader(Paths.get("src/main/resources/input.txt"))
手動で____FileReaderを作成してからラップする必要がないため、ファイルを読み込む場合はこれをバッファリングするのがいいでしょう。
3.2. 1行ずつ読む
次に、
readLine
メソッドを使用してファイルの内容を読みましょう。
public String readAllLines(BufferedReader reader) throws IOException {
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line);
content.append(System.lineSeparator());
}
return content.toString();
}
-
もう少し簡単に言うと、Java 8で導入された
__lines
__methodを使って上記と同じことができます。
public String readAllLinesWithStream(BufferedReader reader) {
return reader.lines()
.collect(Collectors.joining(System.lineSeparator()));
}
3.3. ストリームを閉じる
BufferedReader
を使用した後、その
close()
メソッドを呼び出して、それに関連するすべてのシステムリソースを解放する必要があります。
try-with-resources
ブロックを使用すると、これは自動的に行われます。
try (BufferedReader reader =
new BufferedReader(new FileReader("src/main/resources/input.txt"))) {
return readAllLines(reader);
}
4その他の便利な方法
それでは、
BufferedReader.
で利用可能なさまざまな便利なメソッドに焦点を絞りましょう。
4.1. 1文字の読み方
__read()
__メソッドを使用して単一の文字を読み取ることができます。ストリームの最後まで、コンテンツ全体を文字ごとに読みましょう。
public String readAllCharsOneByOne(BufferedReader reader) throws IOException {
StringBuilder content = new StringBuilder();
int value;
while ((value = reader.read()) != -1) {
content.append((char) value);
}
return content.toString();
}
これは(ASCII値として返された)文字を読み込み、それらを
char
にキャストして結果に追加します。
read()
メソッドからの応答値-1で示されるストリームの終わりまでこれを繰り返します。
4.2. 複数の文字を読む
一度に複数の文字を読みたい場合は、メソッド
read(char[]cbuf、int off、int len)
を使用できます。
public String readMultipleChars(BufferedReader reader) throws IOException {
int length;
char[]chars = new char[length];
int charsRead = reader.read(chars, 0, length);
String result;
if (charsRead != -1) {
result = new String(chars, 0, charsRead);
} else {
result = "";
}
return result;
}
上記のコード例では、最大5文字をchar配列に読み込み、そこから文字列を構成します。読み取りの試行で文字が読み取られなかった場合(つまり、ストリームの終わりに達した場合)、単に空の文字列を返します。
4.3. スキップ文字
skip(long n)
メソッドを呼び出して、指定した数の文字をスキップすることもできます。
@Test
public void givenBufferedReader__whensSkipChars__thenOk() throws IOException {
StringBuilder result = new StringBuilder();
try (BufferedReader reader =
new BufferedReader(new StringReader("1____2____3____4____5"))) {
int value;
while ((value = reader.read()) != -1) {
result.append((char) value);
reader.skip(2L);
}
}
assertEquals("12345", result);
}
上記の例では、2つのアンダースコアで区切られた数字を含む入力文字列から読み取ります。数字だけを含む文字列を作成するために、
_skip
_
methodを呼び出してアンダースコアをスキップします。
4.4.
mark
と
reset
mark(int readAheadLimit)
および
__reset()
methodsメソッドを使用して、ストリーム内のある位置をマークして後で戻ることができます。やや不自然な例として、
mark()
と
reset()__を使用して、ストリームの先頭にあるすべての空白を無視しましょう。
@Test
public void givenBufferedReader__whenSkipsWhitespacesAtBeginning__thenOk()
throws IOException {
String result;
try (BufferedReader reader =
new BufferedReader(new StringReader(" Lorem ipsum dolor sit amet."))) {
do {
reader.mark(1);
} while(Character.isWhitespace(reader.read()))
reader.reset();
result = reader.readLine();
}
assertEquals("Lorem ipsum dolor sit amet.", result);
}
上記の例では、
__ mark()
メソッドを使用して、先ほど読んだ位置にマークを付けます。値を1にすると、コードだけが1文字分のマークを記憶します。
最初の空白以外の文字が見つかったら、ストリーム全体を再処理する必要なくその文字に戻って読み直すことができるので、ここでは便利です。マークを付けないと、最後の文字列で
L__が失われます。
mark()
が
UnsupportedOperationException
をスローする可能性があるため、
markSupported()
を
__mark()を呼び出すコードに関連付けることは非常に一般的です。
ただし、実際には必要ありません。
markSupported()
alwaysが
BufferedReader __に対してtrueを返すからです。
もちろん、私たちは他の方法でもう少し上品に上記のことをすることができるかもしれません、そして実際には
__mark
と
reset__は非常に典型的な方法ではないです。ただし、先読みする必要がある場合は、確かに便利です。
5結論
このクイックチュートリアルでは、
BufferedReader
を使用した実用的な例で文字入力ストリームを読み取る方法を学びました。
最後に、例のソースコードはhttps://github.com/eugenp/tutorials/tree/master/core-java-io[Githubで利用可能]です。