1. 概要

このチュートリアルでは、標準のJava IO API、 Google Guava 、および Apache Commonsを使用して、Javaを使用してファイル内の行数を見つける方法を学習します。 IOライブラリ。

2. NIO2ファイル

このチュートリアルでは、入力ファイル名と合計行数として次のサンプル値を使用することに注意してください。

static final String INPUT_FILE_NAME = "src/main/resources/input.txt";
static final int NO_OF_LINES = 45;

Java 7は、既存のIOライブラリに多くの改善を導入し、 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

次に、 FileChannel、高性能Java NIOの代替手段を確認して、行数を読み取ります。

@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はJDK4で導入されましたが、上記のソリューションはJDK7以降でのみ機能します。

4. GoogleGuavaファイル

別のサードパーティライブラリは、Google Guava Filesクラスです。 このクラスは、 Files#readAllLines で見たのと同様の方法で、行の総数をカウントするためにも使用できます。

pom.xmlguava依存関係を追加することから始めましょう。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-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の並列ソリューションである Apache Commons IO FileUtilsAPIを見てみましょう。

ライブラリを使用するには、commons-io依存関係pom.xmlに含める必要があります。

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

その時点で、Apache CommonsIOの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);
}

ご覧のとおり、これはGoogleGuavaソリューションよりも少し冗長です。

6. BufferedReader

それで、昔ながらの方法はどうですか? JDK 7を使用しておらず、サードパーティのライブラリを使用できない場合は、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、 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);
    }
}

ここでは、スキップメソッドを呼び出してファイルの最後に移動し、行番号が0から始まるため、カウントされた行の総数に1を追加しています。

8. スキャナー

そして最後に、より大きなソリューションの一部としてスキャナーをすでに使用している場合は、問題を解決することもできます。

@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の主な目的は、ファイル内の行数をカウントすることではないため、ニーズに合った適切なソリューションを選択することをお勧めします。

いつものように、このチュートリアルのソースコードは、GitHubからで入手できます。