LoginSignup
77
96

More than 5 years have passed since last update.

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

Posted at

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を使用した方法が最適ではないでしょうか。
では、失礼します。

77
96
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
77
96