Files.readString() / Files.readAllLines()
| 対応: | Java 11(2018) |
|---|
ファイルの内容を文字列または行のリストとして一度に読み込むメソッドです(Java 11+)。Files クラスのユーティリティメソッドを使うことで、従来の BufferedReader よりも少ないコードで読み込みが完結します。
構文
// ファイル全体を文字列として読み込みます(Java 11+)
String content = Files.readString(Path.of("ファイルパス"));
// ファイルの全行をリストとして読み込みます
List<String> lines = Files.readAllLines(Path.of("ファイルパス"));
// ファイルの全行をストリームとして読み込みます(Java 8+)
Stream<String> lineStream = Files.lines(Path.of("ファイルパス"));
// パスオブジェクトを作成します(Java 11+)
Path path = Path.of("ファイルパス");
メソッド一覧
| メソッド | 概要 |
|---|---|
| Files.readString(Path) | ファイル全体を UTF-8 文字列として読み込みます(Java 11+)。文字コードを第2引数で指定することもできます。 |
| Files.readAllLines(Path) | ファイルの全行を List<String> として読み込みます。行末の改行文字は含みません。 |
| Files.lines(Path) | ファイルの全行を Stream<String> として返します(Java 8+)。大きなファイルを遅延読み込みする場合に有効です。 |
| Path.of(String) | 文字列からパスオブジェクトを作成します(Java 11+)。Paths.get() と同等です。 |
サンプルコード
FilesReadstring.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
class FilesReadstring {
public static void main(String[] args) throws IOException {
Path path = Path.of("sample.txt");
Files.writeString(path, "// はじめの行\nHello, World!\n// おわりの行");
String content = Files.readString(path);
System.out.println(content);
List<String> lines = Files.readAllLines(path);
System.out.println("行数: " + lines.size());
for (String line : lines) {
System.out.println(line);
}
try (var stream = Files.lines(path)) {
stream
.filter(line -> line.startsWith("//"))
.forEach(System.out::println);
}
}
}
コンパイルして実行すると次のようになります。
javac FilesReadstring.java java FilesReadstring // はじめの行 Hello, World! // おわりの行 行数: 3 // はじめの行 Hello, World! // おわりの行 // はじめの行 // おわりの行
よくあるミス
よくあるミス1: 存在しないファイルパスを指定してNoSuchFileException
岡部倫太郎が存在しないパスのファイルをreadString()で読もうとしたため、NoSuchFileExceptionが発生しました。
ReadStringNg.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
class ReadStringNg {
public static void main(String[] args) throws IOException {
String content = Files.readString(Path.of("missing.txt"));
System.out.println(content);
}
}
コンパイルして実行すると次のようになります。
javac ReadStringNg.java java ReadStringNg Exception in thread "main" java.nio.file.NoSuchFileException: missing.txt at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) at ReadStringNg.main(ReadStringNg.java:7)
牧瀬紅莉栖が修正したように、Files.exists()で事前確認するか、try-catchで例外を受け取ることで安全に処理できます。
ReadStringOk.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
class ReadStringOk {
public static void main(String[] args) {
Path path = Path.of("missing.txt");
try {
String content = Files.readString(path);
System.out.println(content);
} catch (IOException e) {
System.out.println("ファイルが見つかりません: " + path);
}
}
}
コンパイルして実行すると次のようになります。
javac ReadStringOk.java java ReadStringOk ファイルが見つかりません: missing.txt
よくあるミス2: 大容量ファイルをreadString()で一括読み込みしてOutOfMemoryError
椎名まゆりが数GBのログファイルをreadString()で一括読み込みしようとしたため、OutOfMemoryErrorが発生しました。
ReadStringOomNg.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
class ReadStringOomNg {
public static void main(String[] args) throws IOException {
String content = Files.readString(Path.of("huge_log.txt"));
System.out.println(content.length());
}
}
コンパイルして実行すると次のようになります。
javac ReadStringOomNg.java java ReadStringOomNg Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
橋田至が修正したように、大容量ファイルはBufferedReaderで1行ずつ処理することでメモリ消費を抑えられます。
ReadStringOomOk.java
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
class ReadStringOomOk {
public static void main(String[] args) throws IOException {
int count = 0;
try (BufferedReader reader = Files.newBufferedReader(Path.of("huge_log.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
count++;
}
}
System.out.println("行数: " + count);
}
}
コンパイルして実行すると次のようになります。
javac ReadStringOomOk.java java ReadStringOomOk 行数: 1000000
概要
『readString()』と『readAllLines()』はファイル全体をメモリに読み込むため、数百MB以上の大きなファイルを読み込む場合はメモリ不足になる可能性があります。大きなファイルには『Files.lines()』または BufferedReader を使って1行ずつ処理してください。
『Files.lines()』は Stream を返すため try-with-resources で使用してください。ストリームを閉じないとファイルハンドルが解放されません。デフォルトの文字コードは UTF-8 ですが、異なる場合は第2引数に Charset(例: Charset.forName("Shift_JIS"))を指定します。
ファイルへの書き込みについては『Files.writeString() / Files.write()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。