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