FileInputStream vs FileReader
Asked Answered
P

6

51
FileReader rd=new FileReader("new.mp4");
FileWriter wr=new FileWriter("output.mp4");
int ch;
while((ch=rd.read())!=-1)
  wr.write(ch);

wr.flush();
wr.close();

When I use the FileReader and FileWriter to read and write an mp4 file, the output.mp4 file can't be rendered well. But when I use FileInputStream and FileOutputStream instead it worked well.

So can I conclude FileReader and FileWriter are only for reading and writing text?

Protolithic answered 1/3, 2011 at 13:38 Comment(1)
P
60

Yes, your conclusion is correct subclasses of Reader and Writer are for reading/writing text content. InputStream / OutputStream are for binary content. If you take a look at the documentation:

Reader - Abstract class for reading character streams

InputStream - Abstract class is the superclass of all classes representing an input stream of bytes.

Pontus answered 1/3, 2011 at 13:40 Comment(6)
so i can read only .txt file ..because pdf,word file also contains image files ..isn't itProtolithic
@Protolithic yes, only text files. pdf and doc are complicated formats that need special libraries in order to be meaningfully parsed.Pontus
@Bozho:where can i find these libraries to use in my pgm and did java creators take the stuff for creating the character streams for only reading .txt filesProtolithic
@Protolithic it depends on your exact requirements. You can ask another question asking exactly what you want to obtain from a PDF and/or Doc. But first search around - there are already related questionsPontus
i edited my previous comment ..can you answer for the second questionProtolithic
@Protolithic this is a different question.Pontus
B
41

FileReader (and indeed anything extending Reader) is indeed for text. From the documentation of Reader:

Abstract class for reading character streams.

(Emphasis mine.) Look at the API and you'll see it's all to do with text - char instead of byte all over the place.

InputStream and OutputStream are for binary data, such as mp4 files.

Personally I would avoid FileReader altogether though, as it always uses the system default character encoding - at least before Java 11. Instead, use InputStreamReader around a FileInputStream... but only when you want to deal with text. (Alternatively, use Files.newBufferedReader.)

As an aside, that's a very inefficient way of copying from an input to an output... use the overloads of read and write which read into or write from a buffer - either a byte[] or a char[]. Otherwise you're calling read and write for every single byte/character in the file.

You should also close IO streams in finally blocks so they're closed even if an exception is thrown while you're processing them.

Barbet answered 1/3, 2011 at 13:40 Comment(4)
Herbert Schildt in his book recommends to use character streams so that code can be internationalized. Do you mean using byte streams also won't affect internationalization?Dilapidation
@AmalK: If you're reading data that's binary in nature - such as videos - then there's no context of internationalization. Any recommendation is contextual, and the context must be taken into account when considering the recommendation.Barbet
@John Skeet I'm specifically referring to text data and so was the recommendation. Does writing file using a byte stream affect internationalization since there is no context of character encoding there? How about mentioning that in your answer? Note that since Java 11, FileReader allows specifying the encoding. Also, it would mean a lot if you could answer my latest question :)Dilapidation
@AmalK: This question isn't about text data though. It's about mp4 files. I do specifically call out "Instead, use InputStreamReader around a FileInputStream... but only when you want to deal with text" already.Barbet
P
7

FileInputStream is used for reading streams of raw bytes of data, like raw images. FileReaders, on the other hand, are used for reading streams of characters

The difference between FileInputStream and FileReader is, FileInputStream reads the file byte by byte and FileReader reads the file character by character.

So when you are trying to read the file which contains the character "Č", in FileInputStream will give the result as 196 140, because the ASCII value of Č is 268.

In FileReader will give the result as 268 which is the ASCII value of the char Č.

Postcard answered 29/4, 2014 at 6:24 Comment(0)
M
4

To understand this thoroughly you need to understand what is character and byte stream, so let's have a quick look at that--

Byte Streams

A byte stream access the file byte by byte. Java programs use byte streams to perform input and output of 8-bit bytes. It is suitable for any kind of file, however not quite appropriate for text files. For example, if the file is using a unicode encoding and a character is represented with two bytes, the byte stream will treat these separately and you will need to do the conversion yourself. Byte oriented streams do not use any encoding scheme while Character oriented streams use character encoding scheme(UNICODE). All byte stream classes are descended from InputStream and OutputStream .

Character Stream

A character stream will read a file character by character. Character Stream is a higher level concept than Byte Stream . A Character Stream is, effectively, a Byte Stream that has been wrapped with logic that allows it to output characters from a specific encoding . That means, a character stream needs to be given the file's encoding in order to work properly. Character stream can support all types of character sets ASCII, Unicode, UTF-8, UTF-16 etc. All character stream classes are descended from Reader and Writer.

If you try to read from a .txt file which has been written with Uni-8 encoding which is by default used in java,then reading the file with both Reader and InputStream classes will give the same output.As here each byte represent one character.

I have created few methods which will help you understand the difference between these two terms--FileInputStream reads byte by byte and FileReader reads char by char. Please have some patience and read further to understand this.

Now that you have got an idea about these two streams lets look at the examples to understand how it works internally---

Method to write a some data in a file using Unicode 16 encoding


    public void unicode16Writer() throws Exception {
        try (OutputStream outputStream = new FileOutputStream("output.txt")) {
            Writer writer = new OutputStreamWriter(outputStream, Charset.forName("UTF-16"));
            writer.write("Hello World");
        }
    }

output.txt

Hello World

These are the 3 ways of reading from the file first using FileReader the default way, then using FileInputStream and then using InputStreamReader with Unicode-16 charset(encoding). The comments in the methods are self explanatory please read them to get a clear understanding how it works.

FileReader

    public void fileReaderUnicode8() throws IOException {
        FileReader fr = new FileReader("output.txt");
        int i;
        int j = fr.read();
        /*
         * here it is not able to convert the 
         * int(a byte/8 bits read from the file) to a
         * char as we had used UTF-16 to encode the file so 16 bits 
         * represented one character, but we can use its super class 
         * InputStreamReader to provide the charset(what we used for encoding)
         * which for our case is UTF-16 , then we can
         * easily convert that into char.
         */
        System.out.println("Output of FileReader using default cons(default charset) : " + (char) j);
//              while ((i=fr.read()) != -1) 
//                System.out.print((char) i); 
    }

Output

Output of FileReader using default cons(default charset) : þ

FileInputStream

public void readBytebyByte() throws IOException {
        try (FileInputStream fis = new FileInputStream("output.txt")) {

            int i;
            int j = fis.read();
            /*
             * here it is not able to convert the 
             * int(a byte/8 bits read from the file) to a
             * char as we had used UTF-16 to encode the
             * file so 16 bits represented one
             * character.
             */

            System.out.println("Output of FileInputStream reading byte by byte : " + (char) j);
//              while ((i=fis.read()) != -1) 
//                System.out.print((char) i); 
        }
    }

Output

Output of FileInputStream reading byte by byte : þ

InputStreamReader

/*Here we are using the parent class of FileReader so that 
     *we can set the charset(type of encoding)
     *in its constructor.
     */
    public void unicode16Reader() throws IOException {
        try (InputStream inputStream = new FileInputStream("output.txt")) {
            Reader reader = new InputStreamReader(inputStream, Charset.forName("UTF-16"));
            int data = reader.read();
            System.out.println("uni-16 ISR: " + (char) data);
        //  while(data != -1){
        //      char theChar = (char) data;
        //      data = reader.read();
        //  }

        }
    }

Output

uni-16 ISR: H

Mural answered 19/4, 2020 at 16:32 Comment(0)
E
1

"FileWriter is meant for writing streams of characters. For writing streams of raw bytes, consider using a FileOutputStream."

http://download.oracle.com/javase/1.4.2/docs/api/java/io/FileWriter.html

FileWriter and FileReader are desinged for Streams of chars...

best regards.

Furkan

Elf answered 1/3, 2011 at 13:43 Comment(0)
E
0

A text file can be read using both fileReader and fileInputStream but mp3 and png can only be read using fileInputStream

  1. fileReader reads char by char

  2. fileInputStream reads byte by byte

Excursionist answered 10/7, 2016 at 18:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.