Thursday, September 28, 2023

Difference between FileReader vs FileInputStream in Java? Answer

Even though both FileReader and FileInputStream are used to read data from a file in Java, they are quite different. The main difference between the FileReader and FileInputStream is that one reads data from a character stream while the other reads data from a byte stream. The FileReader automatically converts the raw bytes into characters by using the platform's default character encoding. This means you should use this class if you are reading from a text file that has the same character encoding as the default one. 

If you happen to read a text file encoded in different character encoding then you should use InputStreamReader with specified character encoding. An InputStreamReader is a bridge between byte stream and character stream and can take a FileInputStream as a source. 

Though, it's worth remembering that it caches the character encoding which means you cannot change the encoding scheme programmatically.

As per my recruitment experience, I have often found Java developers good on multi-threading, collections, and basics but fare really poor on Java IO. They struggle to answer questions like channel vs buffer, byte vs character, or IO vs NIO. If you ask them to write code, they never handle the exception, never close the file and hardly write production-quality code.

An interview is a place to write your best code.

Brushing up your IO skills by reading Core Java for Really Impatient is also a good idea, as one reason for lacking Java IO knowledge is the lack of practice. This book, not only explains things well but also gives you lots of exercises to practice well.





Differences between FileReader and FileInputStream in Java

Here are a couple of key differences between a FileReader and a FileInputStream in Java:

1) The first difference is in their type hierarchy, FileReader extends from Reader class while FileInputStream is descendent of InputStream class.

2) The second difference is in their purpose. The FileReader is meant for reading text data while FileInputStream is for reading binary data.

3) The various overloaded read() methods of FileReader can read one character at a time or multiple characters into an array while read() method of FileInputStream can read one byte at a time or multiple bytes in a byte array.

Here is a nice slide that explains the difference between FileReader and FileInputStream quite well:

Difference between FileReader vs FileInputStream in Java



Java Program to Read File using FileReader vs FileInputStream

Let's see an example to learn how to use both FileReader and FileInputStream classes to read data from a text file. Remember, FileReader reads characters while FileInputStream reads bytes. In this program, I have just read the data from the manifest.mf file which is a text file.
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Java Program to demonstrate difference between
 * FileReader and FileInputStream in Java
 *
 * @author WINDOWS 8
 */
public class IteratorRemoveTest {

    public static void main(String args[]) throws IOException {
        
        // reading data using FileReader
        System.out.println("Reding text file using FileReader");
        try {
            FileReader fr = new FileReader("manifest.mf");
            int i = fr.read();
            
            while(i != -1){
                System.out.print((char)i);
                i = fr.read();
            }
           
        } catch (FileNotFoundException ex) {
            Logger.getLogger(IteratorRemoveTest.class.getName())
                       .log(Level.SEVERE, null, ex);
        }
        
        
        // reading data using FileInputStream
        System.out.println("Redding text file using FileInputStream");
        try {
            
            FileInputStream fis = new FileInputStream("manifest.mf");
            int b = fis.read();
            
            while(b != -1){
                System.out.print(b);
                b = fis.read();
            }
            
        } catch (FileNotFoundException ex) {
            Logger.getLogger(IteratorRemoveTest.class.getName())
                 .log(Level.SEVERE, null, ex);
        } 

    }

}

Output:
Redding text file using FileReader
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

Reding text file using FileInputStream
7797110105102101115116458610111411510511111058324
9464813108845677977776978845832779710511045671089711511
53211910510810832981013297100100101100329711711611110997
11610599971081081213298121329811710510810013101310
BUILD SUCCESSFUL (total time: 0 seconds)


That's all on the difference between FileReader and FileInputStream in Java. So, use FileReader if you intend to read streams of character and use the FileInputStream if you want to read streams of raw bytes. 

It's better to use FileReader for reading text files because it will take care of converting bytes to characters but remember that FileReader uses the platform's default character encoding. If you are reading a file that is encoded in a character encoding other than the host's default char encoding then you should use the InputStreamReader.

Thanks a lot for reading this article so far. If you have any questions or feedback then please drop a note in comments. Also, let me know if you have used FileReader class in your project before and any issues or challenges you have faced?

9 comments:

  1. Good, neat explenation. Question: why does main throws IOE instead of catching it in the try statements?

    ReplyDelete
  2. Love reading on Java67 and Javarevisited.... you guys write very clearly to make the concept understandable...

    ReplyDelete
  3. Hi Javin, Can you please clear my confusion on these queries..
    1.Does the difference of these 2 classes boil down to how data is read only and not in how the data TO BE read(ie the file) is stored?
    2. For example we use reader to read form txt file while we use inputstream to read from an excel(apache poi API). Then how come both return characters and not binary data?For eg apache poi api gets the exact cell value in character format and not in binary. So i am really confused

    ReplyDelete
  4. I am also confused as I do not see any difference. The apparent difference seems to be because of the change shown below.
    In case of FileReader we are casting i to char before printing.
    while(i != -1){
    System.out.print((char)i);
    i = fr.read();
    }
    However in case of FileInputStream we are not.
    while(b != -1){
    System.out.print(b);
    b = fis.read();

    I have casted b also to char before printing, so I am able to see the whole text instead of int representation of bytes.

    ReplyDelete
    Replies
    1. Hello Nagraj and Unknown, sorry I see your question now after an year. The difference lies in their purpose - FileReader is meant for reading streams of characters, while For reading streams of raw bytes, consider using a FileInputStream.

      Also, when you use FileReader default character encoding is used.

      Delete
  5. Is it the same meaning even FileOutputStream?

    ReplyDelete
    Replies
    1. Yes, that's correct only difference is that outstream is compared with writer instead of reader because you write on output stream and you read from input stream

      Delete
  6. Probably, OutputStream the same meaning.

    ReplyDelete
  7. the writing is very good, i actually understand it , thank you .

    ReplyDelete

Feel free to comment, ask questions if you have any doubt.