开发者

FileInputStream vs FileReader

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. B开发者_Go百科ut when I use FileInputStream and FileOutputStream instead it worked well.

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


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.


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.


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 Č.


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


"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


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜