Javaを使用してファイル内の行数を見つける

1. 概要

このチュートリアルでは、標準のJava IO API、https://www.baeldung.com/category/guava/ [__Google Guav__a]を使用して、* Javaを使用してファイル内の行数を見つける方法を学習します。 _https://www.baeldung.com/apache-commons-io [Apache Commons IO] _ライブラリ。

2. NIO2 ファイル

このチュートリアルでは、入力ファイル名と合計行数として次のサンプル値を使用します。
static final String INPUT_FILE_NAME = "src/main/resources/input.txt";
static final int NO_OF_LINES = 45;
Java 7は、既存のIOライブラリに多くの改善を導入し、https://www.baeldung.com/java-nio-2-file-api [NIO2:]の下にパッケージ化しました。
_Files_から始めて、そのAPIを使用して行数をカウントする方法を見てみましょう。
@Test
public void whenUsingNIOFiles_thenReturnTotalNumberOfLines() throws IOException {
    try (Stream<String> fileStream = Files.lines(Paths.get(INPUT_FILE_NAME))) {
        int noOfLines = (int) fileStream.count();
        assertEquals(NO_OF_LINES, noOfLines);
    }
}
または、単に_Files#readAllLines_メソッドを使用して:
@Test
public void whenUsingNIOFilesReadAllLines_thenReturnTotalNumberOfLines() throws IOException {
    List<String> fileStream = Files.readAllLines(Paths.get(INPUT_FILE_NAME));
    int noOfLines = fileStream.size();
    assertEquals(NO_OF_LINES, noOfLines);
}

3. NIO FileChannel

行数を読み取るための高性能のJava NIOの代替手段である_FileChannelを確認しましょう。
@Test
public void whenUsingNIOFileChannel_thenReturnTotalNumberOfLines() throws IOException {
    int noOfLines = 1;
    try (FileChannel channel = FileChannel.open(Paths.get(INPUT_FILE_NAME), StandardOpenOption.READ)) {
        ByteBuffer byteBuffer = channel.map(MapMode.READ_ONLY, 0, channel.size());
        while (byteBuffer.hasRemaining()) {
            byte currentByte = byteBuffer.get();
            if (currentByte == '\n')
                noOfLines++;
       }
    }
    assertEquals(NO_OF_LINES, noOfLines);
}
_FileChannel_はJDK 4で導入されましたが、*上記のソリューションはJDK 7以降でのみ機能します*。

4. Google Guava Files

代替のサードパーティライブラリは、Google Guava _Files_クラスです。 このクラスは、_Files#readAllLines_で見たのと同様の方法で行の総数をカウントするためにも使用できます。
まず、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22com.google.guava%22%20AND%20a%3A%22guava%22 [the _guava_dependency]を追加することから始めましょう。 _pom.xml_:
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.0-jre</version>
</dependency>
そして、__readLines __を使用して、ファイル行の_List_を取得できます。
@Test
public void whenUsingGoogleGuava_thenReturnTotalNumberOfLines() throws IOException {
    List<String> lineItems = Files.readLines(Paths.get(INPUT_FILE_NAME)
      .toFile(), Charset.defaultCharset());
    int noOfLines = lineItems.size();
    assertEquals(NO_OF_LINES, noOfLines);
}

5. Apache Commons IO FileUtils

それでは、Guavaの並列ソリューションであるlink:/apache-commons-io[Apache Commons IO] _FileUtils_ APIを見てみましょう。
ライブラリを使用するには、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22commons-io%22%20AND%20a%3A%22commons-io%22 [ _pom.xml_のcommons-io依存関係]:
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
その時点で、Apache Commons IO FileUtils#lineIterator_を使用できます。これにより、ファイル処理の一部がクリーンアップされます。
@Test
public void whenUsingApacheCommonsIO_thenReturnTotalNumberOfLines() throws IOException {
    int noOfLines = 0;
    LineIterator lineIterator = FileUtils.lineIterator(new File(INPUT_FILE_NAME));
    while (lineIterator.hasNext()) {
        lineIterator.nextLine();
        noOfLines++;
    }
    assertEquals(NO_OF_LINES, noOfLines);
}
ご覧のとおり、これはGoogle Guavaソリューションよりも少し冗長です。

6. _ BufferedReader _

では、昔ながらの方法はどうですか? JDK 7を使用しておらず、サードパーティのライブラリを使用できない場合、https://www.baeldung.com/java-buffered-reader [_BufferedReader_]があります。
@Test
public void whenUsingBufferedReader_thenReturnTotalNumberOfLines() throws IOException {
    int noOfLines = 0;
    try (BufferedReader reader = new BufferedReader(new FileReader(INPUT_FILE_NAME))) {
        while (reader.readLine() != null) {
            noOfLines++;
        }
    }
    assertEquals(NO_OF_LINES, noOfLines);
}

7. LineNumberReader

または、_LineNumberReader、_https://www.baeldung.com/java-buffered-reader [BufferedReader] _の直接のサブクラスを使用できますが、これは少し冗長です。
@Test
public void whenUsingLineNumberReader_thenReturnTotalNumberOfLines() throws IOException {
    try (LineNumberReader reader = new LineNumberReader(new FileReader(INPUT_FILE_NAME))) {
        reader.skip(Integer.MAX_VALUE);
        int noOfLines = reader.getLineNumber() + 1;
        assertEquals(NO_OF_LINES, noOfLines);
    }
}
ここでは、* skip_メソッドを呼び出してファイルの最後に移動し、*行の番号付けが0から始まるため、カウントされた行の合計数に1を追加しています*。

8. スキャナー

最後に、より大きなソリューションの一部として__https://www.baeldung.com/java-scanner [Scanner] ___を既に使用している場合、問題を解決することもできます。
@Test
public void whenUsingScanner_thenReturnTotalNumberOfLines() throws IOException {
    try (Scanner scanner = new Scanner(new FileReader(INPUT_FILE_NAME))) {
        int noOfLines = 0;
        while (scanner.hasNextLine()) {
            scanner.nextLine();
            noOfLines++;
        }
        assertEquals(NO_OF_LINES, noOfLines);
    }
}

9. 結論

このチュートリアルでは、Javaを使用してファイル内の行数を見つけるさまざまな方法を検討しました。 これらすべてのAPIの主な目的はファイル内の行数をカウントすることではないため、必要に応じて適切なソリューションを選択することをお勧めします。
いつものように、このチュートリアルのソースコードはhttps://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-nio[GitHubで]から入手できます。