1. Overview
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
Let's start by creating a simple file named inputLines.txt that we'll use in all of our examples:
Line 1
Line 2
Line 3
Line 4
Line 5
3. Using BufferedReader
Let's look at the well known BufferedReader class and its advantage of not storing the entire file into memory.
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
Another similar approach we can take is using a 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.1. Small Files
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:
@Test
public void givenSmallFile_whenUsingFilesAPI_thenExtractedLineIsCorrect() {
String extractedLine = Files.readAllLines(Paths.get(FILE_PATH)).get(4);
assertEquals("Line 5", extractedLine);
}
5.2. Large Files
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:
@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
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:
@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:
@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
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.