Java
java8

ファイル読み込みは何がベストなのか(Java)

More than 1 year has passed since last update.

Javaのファイル読み込みにはたくさんの方法がありますが、どの方法が一番早いのか測定してみた。

今回は全行読み込みにて測定してみました。


対象

1.Files.readAllLines

Java7から導入されているjava.nio.file.FilesのreadAllLinesを利用したファイルの全行読み込みです。

内部的には、BufferedReaderを作成して、1行づつ読み込んでListに設定して返却しているだけです。

try {

List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}

2.FileReaderを使用。

従来からのやり方です。FileReaderでFileを読み込んで、BufferedReaderでラップします。

文字コードは、環境の文字コードをそのまま利用します。文字コードを指定したい場合は、使えません。

try (BufferedReader reader = new BufferedReader(new FileReader(file));){

String str;
List<String> lines = new ArrayList<>();
while ((str = reader.readLine()) != null) {
lines.add(str);
}
} catch (IOException e) {
e.printStackTrace();
}

3.FileInputStreamを使用。

従来のやり方で、文字コードを使用した場合に使う方法です。

FileInputStreamでファイルを読み込んで、InputStreamReaderで文字コードを指定します。

そして、BufferedReaderでラップします。

try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));){

String str;
List<String> lines = new ArrayList<>();
while ((str = reader.readLine()) != null) {
lines.add(str);
}
} catch (IOException e) {
e.printStackTrace();
}

4.Files.readAllLinesを使用。

Java8から追加された関数で、ファイルの全行をStreamで返却します。

その値を終端処理でリストにしています。

try {

List<String> lines = Files.lines(path, StandardCharsets.UTF_8).collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}


実行してみた

以下のソースで実行してみました

TestFileは20万行のテキストファイルです。

private static final String PATH = "src/test/java/com/test/common/TestFile";

public static void main(String[] args) {
Path path = Paths.get(PATH);
File file = path.toFile();
// Files.readAllLinesの測定
Runnable test1 = () -> {
try {
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
};

// BufferedReader FileReaderの測定
Runnable test2 = () -> {
try (BufferedReader reader = new BufferedReader(new FileReader(file));){
String str;
List<String> lines = new ArrayList<>();
while ((str = reader.readLine()) != null) {
lines.add(str);
}
} catch (IOException e) {
e.printStackTrace();
}
};

// BufferedReader InputStreamReader FileInputStreamの測定
Runnable test3 = () -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));){
String str;
List<String> lines = new ArrayList<>();
while ((str = reader.readLine()) != null) {
lines.add(str);
}
} catch (IOException e) {
e.printStackTrace();
}
};

// Files.readAllLinesの測定
Runnable test4 = () -> {
try {
List<String> lines = Files.lines(path, StandardCharsets.UTF_8).collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
};

calcFuncTime(test1);
calcFuncTime(test2);
calcFuncTime(test3);
calcFuncTime(test4);
}

/**
* 時間を測定する
* @param runnable
*/

private static void calcFuncTime(Runnable runnable) {
long start = System.nanoTime();
runnable.run();
long end = System.nanoTime();
System.out.println(end - start);
}


実行結果

101206619

178792154
53933069
102386121


一番良いのはなにか

実行結果を確認すると一番遅いのが2つ目に実施したケースで、1番早いのが3つ目に実施したケースになりました。

といっても0.1秒程度の違いなので、20万行でこの程度の差異ならばほとんど気にしなくても良いのではないかと思います。

個人的には、FileReaderを使用する方法は、文字コードも使用できないし遅いしあまりお勧めできませんね。

FileInputStreamを使用する方法が一番早いですが、記述量が多いのでFilesを使用した方法が最適ではないでしょうか。

では、失礼します。