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

The number of total classes of Java I/O is large, and it is easy to get confused when to use which. The following are two methods for reading a file line by line.

Method 1:

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) {

Method 2:

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) {

Use the following code:

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

Both works for reading a text file line by line.

The difference between the two methods is what to use to construct a BufferedReader. Method 1 uses InputStreamReader and Method 2 uses FileReader. What's the difference between the two classes?

From Java Doc, "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 "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.

In summary, InputStreamReader is always a safer choice than FileReader.

It is worth to mention here that instead of using a concrete / or \\ for a path, you should always use File.separator which can ensure that the separator is always correct for different operating systems. Also the path used should be relative, and that ensures the path is always correct.

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

Reading the class hierarchy diagram is also very helpful for understanding those inputstream and reader related concept:


Category >> I/O  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
String foo = "bar";
  • Wittahera

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

  • ahmed

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