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。