Find the Number of Lines in a File Using Java – 用Java查找文件中的行数

最后修改: 2019年 8月 11日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll learn how to find the number of lines in a file using Java with the help of standard Java IO APIs, Google Guava and the Apache Commons IO library.

在本教程中,我们将学习如何在标准Java IO API、Google GuavaApache Commons IO库的帮助下使用Java查找文件的行数。

2. NIO2 Files

2.NIO2文件

Note that, across this tutorial, we’ll be using the following sample values as the input file name and the total number of lines:

注意,在本教程中,我们将使用以下样本值作为输入文件名和总行数。

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

Java 7 introduced many improvements to the existing IO libraries and packaged it under NIO2:

Java 7对现有的IO库进行了许多改进,并将其打包在NIO2:下。

Let’s start with Files and see how can we use its API to count the numbers of lines:

让我们从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);
    }
}

Or by simply using Files#readAllLines method:

或者简单地使用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

3.NIO文件通道

Now let’s check FileChannel, a high-performance Java NIO alternative to read the number of lines:

现在让我们检查一下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);
}

Though the FileChannel was introduced in JDK 4, the above solution works only with JDK 7 or higher.

虽然FileChannel是在JDK 4中引入的,但上述解决方案仅适用于JDK 7或更高版本

4. Google Guava Files

4.Google GuavaFiles

An alternative third-party library would be Google Guava Files class. This class can also be used to count the total number of lines in a similar way to what we saw with Files#readAllLines.

另一个第三方库是Google Guava的Files类。这个类也可以用来计算总行数,方法与我们看到的Files#readAllLines相似。

Let’s start by adding the guava dependency in our pom.xml:

让我们先在pom.xml中添加guava依赖项。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

And then we can use readLines to get a List of file lines:

然后我们可以使用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

5.Apache Commons IOFileUtils

Now, let’s see Apache Commons IO FileUtils API, a parallel solution to Guava.

现在,让我们看看Apache Commons IO FileUtils API,一个与Guava并行的解决方案。

To use the library, we have to include the commons-io dependency in the pom.xml:

要使用该库,我们必须在pom.xml中包括commons-io依赖项

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

At that point, we can use Apache Commons IO’s FileUtils#lineIterator, which cleans up some of the file handlings for us:

在这一点上,我们可以使用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);
}

As we can see, this is a bit more verbose than the Google Guava solution.

正如我们所看到的,这比Google Guava的解决方案更繁琐一些。

6. BufferedReader

6.BufferedReader

So, what about old-school ways? If we aren’t on JDK 7 and we can’t use a third-party library, we have 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

7.LineNumberReader(行数阅读器)

Or, we can use LineNumberReader, a direct subclass of BufferedReader, which is just a bit less verbose:

或者,我们可以使用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);
    }
}

Here we are calling the skip method to go to the end of the file, and we’re adding 1 to the total number of lines counted since the line numbering begins at 0.

这里我们调用skip方法到文件的末尾,我们在计算的总行数上加1,因为行数从0开始。

8. Scanner

8.扫描器

And finally, if we’re already using Scanner as part of a larger solution, it can solve the problem for us, too:

最后,如果我们已经在使用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. Conclusion

9.结语

In this tutorial, we have explored different ways to find the number of lines in a file using Java. Since the main purpose of all these APIs is not for counting the number of lines in a file, it’s recommended choosing the right solution for our need.

在本教程中,我们探讨了使用Java查找文件中的行数的不同方法。由于所有这些API的主要目的不是为了计算文件中的行数,所以建议根据我们的需要选择合适的解决方案。

As always, the source code for this tutorial is available over on GitHub.

像往常一样,本教程的源代码可在GitHub上获得over