チュートリアル
Javaのファイル読み込みにはたくさんの実装方法が存在します。では、どの方法が読み込み速度が速いのでしょうか?
今回はいくつかの実装方法で検証してみました。
測定方法
以下の対象ファイルの読み込み、処理時間を測定する。
測定は3回実施する。
ファイルサイズ | 約306 MB |
---|---|
ファイル行数 | 100万行※1行あたり平均320バイト程度 |
使用クラス
以下の3クラスを使用して、ファイルの読み込み処理を実装する。
- java.io.FileReader#readLin(1行読み込み)
- java.io.FileInputStream#readLin(1行読み込み)
- java.nio.file.Files#lines(全行読み込み)
ケース1:java.io.FileReader#readLin(1行読み込み)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/** * FileReaderを使用してファイルを読み込みます。 * @param filePath ファイルパス * @return 読み込み内容 */ public static List readFileCase1(String filePath) { BufferedReader br = null; FileReader fr = null; List list = new ArrayList(); try { // FileReaderで読み込むファイルを指定 fr = new FileReader(filePath); // 文字型入力ストリームからテキストを読み込み br = new BufferedReader(fr); // 1行ごとに読み込み String line = null; while ((line = br.readLine()) != null) { list.add(line); } return list; } catch (IOException e) { e.printStackTrace(); return null; } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } |
ケース2:java.io.FileInputStream#readLin(1行読み込み)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/** * FileInputStreamを使用してファイルを読み込みます。 * @param filePath ファイルパス * @return 読み込み内容 */ public static List readFileCase2(String filePath) { BufferedReader br = null; FileInputStream fis = null; List list = new ArrayList(); try { // InputStreamReaderで読み込むファイルを指定 fis = new FileInputStream(filePath); // 文字型入力ストリームからテキストを読み込み br = new BufferedReader(new InputStreamReader(fis)); // 1行ごとに読み込み String line = null; while ((line = br.readLine()) != null) { list.add(line); } return list; } catch (IOException e) { e.printStackTrace(); return null; } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } |
ケース3:java.nio.file.Files#lines(全行読み込み)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/** * Filesを使用してファイルを読み込みます。 * @param filePath ファイルパス * @return 読み込み内容 */ public static List readFileCase3(String filePath) { Stream stream = null; try { // パスを指定 Path path = Paths.get(filePath); // ファイル内のすべての行をStreamとして読み込む stream = Files.lines(path); return stream.collect(Collectors.toList()); } catch (IOException e) { e.printStackTrace(); return null; } finally { if (stream != null) { stream.close(); } } } |
テストコード(JUnit)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import java.util.List; import org.junit.jupiter.api.Test; import sample.code.FileRead; class FileReadTest { // 読み込みファイル private static final String READ_FILE = "D:\\temp\\sample.txt"; @Test void test01() { long startTime = System.currentTimeMillis(); List list = FileRead.readFileCase1(READ_FILE); long endTime = System.currentTimeMillis(); System.out.println("処理時間:" + (endTime - startTime) + " ms / 読み込み行数:" + list.size()); } @Test void test02() { long startTime = System.currentTimeMillis(); List list = FileRead.readFileCase2(READ_FILE); long endTime = System.currentTimeMillis(); System.out.println("処理時間:" + (endTime - startTime) + " ms / 読み込み行数:" + list.size()); } @Test void test03() { long startTime = System.currentTimeMillis(); List list = FileRead.readFileCase3(READ_FILE); long endTime = System.currentTimeMillis(); System.out.println("処理時間:" + (endTime - startTime) + " ms / 読み込み行数:" + list.size()); } } |
測定結果
各3回実施した結果、以下の通りとなった。
実装 | 測定1回目 | 測定2回目 | 測定3回目 |
---|---|---|---|
ケース1 | 2852 ms | 3034 ms | 2901 ms |
ケース2 | 3065 ms | 2969 ms | 2659 ms |
ケース3 | 3022 ms | 2789 ms | 2963 ms |
※赤文字:最速
ファイル読み込みを各3回実施してみた結果、最速は都度変わる結果となった。
また、2位、3位と比較した場合も、ほぼ誤差程度の違いしか見られなかった。
結局どれが速いか?は決められない結果となった。
実装は好みにお任せします。