Java read a file line by line – How Many Ways?

Processing a text file line by line is a common thing programmers do. There are many related classes in the Java I/O package and this may get confusing. This post shows 4 different ways of reading a file line by line in Java.

1. FileInputStream and BufferedReader

private static void readFile1(File fin) throws IOException {
	FileInputStream fis = new FileInputStream(fin);
 
	//Construct BufferedReader from InputStreamReader
	BufferedReader br = new BufferedReader(new InputStreamReader(fis));
 
	String line = null;
	while ((line = br.readLine()) != null) {
		System.out.println(line);
	}
 
	br.close();
}

2. FileReader and BufferedReader

private static void readFile2(File fin) throws IOException {
	// Construct BufferedReader from FileReader
	BufferedReader br = new BufferedReader(new FileReader(fin));
 
	String line = null;
	while ((line = br.readLine()) != null) {
		System.out.println(line);
	}
 
	br.close();
}

Use the following code:

//use . to get current directory
File dir = new File(".");
File fin = new File(dir.getCanonicalPath() + File.separator + "in.txt");
 
readFile1(fin);
readFile2(fin);

Both works for reading a text file line by line.

The difference between the two methods is how to construct a BufferedReader object. Method 1 uses InputStreamReader and Method 2 uses FileReader. What’s the difference between the two classes? An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset. InputStreamReader can handle other input streams than files, such as network connections, classpath resources, ZIP files, etc.

FileReader is a convenience class for reading character files. The constructors of this class assume that the default character encoding and the default byte-buffer size are appropriate. FileReader does not allow you to specify an encoding other than the platform default encoding. Therefore, it is not a good idea to use it if the program will run on systems with different platform encoding.

Comparing Method 1 & 2, InputStreamReader is a safer choice than FileReader.

3. Files.newBufferedReader()

You can also use the following method which is available since Java 1.7. Essentially, it is the same with Method 1.

Charset charset = Charset.forName("US-ASCII");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
    String line = null;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException x) {
    System.err.format("IOException: %s%n", x);
}

The newBufferedReader() method does the following:

public static BufferedReader newBufferedReader(Path path, Charset cs){
 CharsetDecoder decoder = cs.newDecoder();
 Reader reader = new InputStreamReader(newInputStream(path), decoder);
 return new BufferedReader(reader);
}

4. Lambda in Java 8

From Java 8, we can use a single line to read a file line by line.

 Files.lines(new File("test.txt").toPath()).map(s -> s.trim())
                            .filter(s -> s.startsWith("abc")
                            .forEach(System.out::println);

Reading the class hierarchy diagram is also very helpful for understanding those inputstream and reader related concept: http://www.programcreek.com/2012/05/java-io-class-hierarchy-diagram/.

5 thoughts on “Java read a file line by line – How Many Ways?”

  1. In the fourth example there is a small mistake – missing bracket. Correct:
    .filter(s -> s.startsWith(“abc”))

  2. Scanner and Printwriter are more convenient IMO. Both Byte Stream and Character Stream are lower level implementations.

  3. may be it is too late feedback but when I tried them BufferedReader method close() also is throwable exception
    Thanks

Leave a Comment