Reading a Line at a Given Line Number From a File in Java – 在Java中以给定的行号从文件中读出一个行

最后修改: 2020年 8月 23日

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

1. Overview

1.概述

In this quick article, we’re going to look at different ways of reading a line at a given line number inside a file.

在这篇简短的文章中,我们将看看在文件中读取指定行号的不同方法。

2. Input File

2.输入文件

Let’s start by creating a simple file named inputLines.txt that we’ll use in all of our examples:

让我们先创建一个名为inputLines.txt的简单文件,我们将在所有的例子中使用它。

Line 1
Line 2
Line 3
Line 4
Line 5

3. Using BufferedReader

3.使用BufferedReader

Let’s look at the well known BufferedReader class and its advantage of not storing the entire file into memory.

让我们看看众所周知的BufferedReader类和它不把整个文件存储到内存中的优势。

We can read a file line by line and stop when we desire:

我们可以逐行读取一个文件,并在我们希望的时候停止:

@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. Using Scanner

4.使用扫描器

Another similar approach we can take is using a Scanner:

我们可以采取的另一个类似的方法是使用一个Scanner

@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);
    }
}

Although on small files, the difference between BufferedReader and Scanner might not be noticeable, on larger files, the Scanner will be slower since it also does parsing and has a smaller buffer size.

尽管在小文件上,缓冲读取器扫描器之间的差异可能并不明显,但在大文件上,扫描器会更慢,因为它也进行解析,并且缓冲区大小更小。

5. Using the File API

5.使用文件API

5.1. Small Files

5.1.小文件

We can use Files.readAllLines() from the File API to easily read the contents of a file into memory and extract the line we desire:

我们可以使用文件API中的Files.readAllLines()来轻松地将文件的内容读入内存,并提取我们想要的那一行。

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

    assertEquals("Line 5", extractedLine);
}

5.2. Large Files

5.2.大型文件

If we need to work with large files, we should use the lines method, which returns a Stream so that we can read the file line by line:

如果我们需要处理大文件,我们应该使用lines方法,它返回一个Stream,这样我们就可以逐行读取文件:

@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. Using Apache Commons IO

6.使用Apache Commons IO

Another option is using the FileUtils class of the commons-io package, which reads the whole file and returns the lines as a list of Strings:

另一个选择是使用commons-io包的FileUtils类,它读取整个文件并将行数作为Strings的列表返回。

@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);
}

We can also use the IOUtils class to achieve the same result, except this time, the whole content is returned as a String, and we have to do the splitting ourselves:

我们也可以使用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. Conclusion

7.结语

In this quick article, we’ve gone over the most common ways of reading a line at a given line number from a file.

在这篇快速文章中,我们介绍了从文件中读取指定行号的行的最常用方法。

As usual, the examples are available over on GitHub.

像往常一样,这些例子可以在GitHub上找到over