Byte streams vs Character streams

April 20, 2011 | I/O streams in java

Byte streams vs Character streams: Character streams Advantages over Byte streams

Byte streams read bytes that fall under ASCII range and character streams read Unicode characters that include characters of many international languages. Being latest, introduced with JDK 1.1, the character streams are advantageous over byte streams like the inclusion of newLine() method (that is not deprecated) with BufferedReader. BufferedWriter includes a overloaded write() method that can write a whole string or a part of a string; but the writeBytes() method of DataOutputStream is not overloaded and writes a whole line (but not part).

Sometimes, byte streams are more efficient to read binary data like the files containing images and sound.

To bridge or link byte streams with character streams, there comes two classes InputStreamReader and OutputStreamWriter. Many byte streams (not all) have equivalent classes in character streams like FileInputStream equivalent FileReader and FileOutputStream equivalent to FileWriter etc.

Character streams - Reader and Writer

The character streams are capable to read 16-bit characters (byte streams read 8-bit characters). Character streams are capable to translate implicitly 8-bit data to 16-bit data or vice versa. The two super-most classes from which all character streams are derived are Reader and Writer. Following hierarchies can be referred for the list of all character streams.

Byte streams vs Character streams

Byte streams vs Character streams

File copying with Character Streams

The files can be read with character streams also. In the following program, file to file copying is done with FileReader and FileWriter. It is equivalent to FileToFile1.java of byte streams copying.

import java.io.*;
public class FileToFile2
{
  public static void main(String args[]) throws IOException
  {
    FileReader fr = new FileReader("pqr.txt");  
    FileWriter fw = new FileWriter("xyz.txt");   
       
    int temp;
    while( ( temp = fr.read() ) != -1 )
    {
      fw.write(temp);   			// writes to xyz.txt
      System.out.print((char) temp);   	// at DOS prompt
    }
    fw.close();
    fr.close();
  }
}

FileReader fr = new FileReader("pqr.txt"); FileWriter fw = new FileWriter("xyz.txt");

The explanation of this program is the same of byte streams illustrated in FileToFile1.java. The pqr.txt is the source file opened with FileReader constructor in read mode. Similarly xyz.txt is the destination file opened with FileWriter constructor in write mode. In case of byte sterams, the classes used are FileInputStream and FileOutputStream.

FileWriter fw = new FileWriter("xyz.txt", true);

The optional second boolean parameter true opens the file, "xyz.txt", in append mode.

while( ( temp = fr.read() ) != -1 )

The read() method of FileReader reads one byte at a time from the source file, converts into ASCII (ASCII is a subset of Unicode) integer value and returns. For example if 'A' is there in the source file, the read() method reads it and converts to 65 and returns. The same method returns -1 if EOF is encountered while reading. That is, every byte read is checked against -1 and then control enters the loop.

fw.write(temp); System.out.print((char) temp);

The write(temp) method of FileWriter takes the ASCII value, converts back to the original character and then writes to the destination file. To write to the DOS prompt with println() method, the ASCII value is converted to char explicitly and then written.

fw.close(); fr.close();

When the job is over, close the streams in the order of first writer stream and then reader stream to have proper flushing of data.

Note: If the streams are not closed properly, sometimes buffers (maintained internally by the system) are not cleared and thereby data will not be not seen in the destination file.