1. 概要

この簡単な記事では、ファイル内の特定の行番号で行を読み取るさまざまな方法を見ていきます。

2. 入力ファイル

すべての例で使用するinputLines.txtという名前の単純なファイルを作成することから始めましょう。

Line 1
Line 2
Line 3
Line 4
Line 5

3. BufferedReaderを使用する

よく知られているBufferedReaderクラスと、ファイル全体をメモリに保存しないことの利点を見てみましょう。

ファイルを1行ずつ読み取り、必要に応じて停止できます。

@Test
public void givenFile_whenUsingBufferedReader_thenExtractedLineIsCorrect() {
    try (BufferedReader br = Files.newBufferedReader(Paths.get(FILE_PATH))) {
        for (int i = 0; i < 3; i++) {
            br.readLine();
        }

        String extractedLine = br.readLine();
        assertEquals("Line 4", extractedLine);
    }
}

4. スキャナーを使用する

私たちが取ることができる別の同様のアプローチは、スキャナーを使用することです:

@Test
public void givenFile_whenUsingScanner_thenExtractedLineIsCorrect() {
    try (Scanner scanner = new Scanner(new File(FILE_PATH))) {
        for (int i = 0; i < 3; i++) {
            scanner.nextLine();
        }

        String extractedLine = scanner.nextLine();
        assertEquals("Line 4", extractedLine);
    }
}

小さいファイルでは、BufferedReaderScannerの違いは目立たないかもしれませんが、大きいファイルでは、 Scanner するため、遅くなります。 parsing であり、バッファサイズが小さくなっています。

5. ファイルAPIの使用

5.1. 小さなファイル

File APIFiles.readAllLines()を使用して、ファイルの内容をメモリに簡単に読み取り、必要な行を抽出できます。

@Test
public void givenSmallFile_whenUsingFilesAPI_thenExtractedLineIsCorrect() {
    String extractedLine = Files.readAllLines(Paths.get(FILE_PATH)).get(4);

    assertEquals("Line 5", extractedLine);
}

5.2. 大きなファイル

大きなファイルを処理する必要がある場合は、 lines メソッドを使用する必要があります。このメソッドは、 Stream を返し、ファイルを1行ずつ読み取ることができます。

@Test
public void givenLargeFile_whenUsingFilesAPI_thenExtractedLineIsCorrect() {
    try (Stream lines = Files.lines(Paths.get(FILE_PATH))) {
        String extractedLine = lines.skip(4).findFirst().get();

        assertEquals("Line 5", extractedLine);
    }
}

6. ApacheCommonsIOの使用

別のオプションは、commons-ioパッケージのFileUtilsクラスを使用することです。これは、ファイル全体を読み取り、Stringのリストとして行を返します。

@Test
public void givenFile_whenUsingFileUtils_thenExtractedLineIsCorrect() {
    ClassLoader classLoader = getClass().getClassLoader();
    File file = new File(classLoader.getResource("linesInput.txt").getFile());

    List<String> lines = FileUtils.readLines(file, "UTF-8");

    String extractedLine = lines.get(0);
    assertEquals("Line 1", extractedLine);
}

IOUtils クラスを使用して同じ結果を達成することもできますが、今回はコンテンツ全体が String として返され、自分で分割する必要があります。

@Test
public void givenFile_whenUsingIOUtils_thenExtractedLineIsCorrect() {
    String fileContent = IOUtils.toString(new FileInputStream(FILE_PATH), StandardCharsets.UTF_8);

    String extractedLine = fileContent.split(System.lineSeparator())[0];
    assertEquals("Line 1", extractedLine);
}

7. 結論

この簡単な記事では、ファイルから特定の行番号の行を読み取る最も一般的な方法について説明しました。

いつものように、例はGitHubから入手できます。