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
fileReader
reads char by charfileInputStream
reads byte by byte
精彩评论