Java IO - Byte and Character streams


basics of java io, using byte stream and character stream, what is buffer and how it is useful in java io, what is java.io and java.nio, how you can internaionalize the file input output learn it all in this post.

The Input output is the basic need of any language, because even if you have a good deal of primary memory but we all know it is volatile. So we must store/retrieve the information and data to and from storage devices for later use. So like any programming language, Java also has in built support for Input Output of data.

Java uses the stream structure to work the IO process, The stream means, the set of binary data in the minimum transmissible chunk. The stream is just the set of binary 0s and 1s which defines the data itself. The use of stream structure is preferred because it makes the operation faster.

Stream in Java

Java also provide a larger scope for IO, by dividing it into the two types of stream, known as Byte Stream and Character Stream. The root purpose is to provide the hardware support along with the internationalization of data. Character set may vary from one country to other so, at base level the stream provides the compatibility, but on the top level character stream takes control.

In this part we are going to discuss only the two types of stream along with the class support java provide to both these types.

The Java language developers have now gone further in terms of defining the IO structure and they have introduced a new version in Java 7, that is java.nio this is another addition to java.io and some of class movement has also been done there. Most of the byte and character stream control classes are in java.io and File operations have been moved mostly to java.nio.

The scope of our discussion here will be limited to byte and character streams only.

The java has provide an identification pattern for the byte and character streams, all the classes incorporating the byte stream ends with either InputStream or OutputStream except for very few like RandomAccessFile or PrintStream etc. Similarly the mark of identification for the Character Stream is Reader or Writer as the Postfix to class name.

And you will find that most of the classes in the Byte and character streams are identical and you can easily know if this is a equivelent counterpart in other stream. for example

FileInputStream <==> FileReader
FileOutpurStream <==> FileWriter
BufferedInputStream <==> BufferedReader
BufferedOutputStream <==> BufferedWriter
PipedInputStream <==> PipedReader
PipedOutputStream <==> PipedWriter

so now let us not waste much time and move on to some basic programming. We will be creating programs which will read a file using byte and character stream and than write into another file.

Note: Please note that the java.io classes throws the IOException so you must always take care about this exception.

we are going to use an input file named "inputfile.txt" which contains following lines.

line one in input file.
line two in input file.
line three in input file.
last line in input file.

Note: you must be careful with the path of file relative to the class file of the program accessing the file, or it may cause you FileNotFoundException.

The following program will tell you about the use of Byte stream.


package IO;
import java.io.*;

public class ByteStream {
    public static void main(String[] args) throws IOException{
        FileInputStream is = null;
        FileOutputStream os = null;
        try{
            /*String curDir = System.getProperty("user.dir");
            System.out.println(curDir);*/
            is = new FileInputStream("inputfile.txt");
            os = new FileOutputStream("outfile.txt");
            int buffer;
            while((buffer = is.read()) != -1){
                System.out.print(buffer);
                os.write(buffer);
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
        finally{
            if(is!=null)
            is.close();
            if(os!=null)
            os.close();
        }
        
    }
}

The output of this program will be nothing if we remove the System.out.print() from the while loop. The main purpose of this program is to read data from one file and then write into another file. This is to be noted that the input file must exist to the specified path/directory. If the output file in non existing the program will create it and write into it.

the output of the program is following,

10810511010132111110101321051103210511011211711632102105108101461010810511010132116119111321051103210511011211711632102105108101461010810511010132116104114101101321051103210511011211711632102105108101461010897115116321081051101013210511032105110112117116321021051081014610

Now what We have done in the program?, First of all We created the object for stream, FileInputStream, FileOutputStream this will act for reading and writing the data in files. In while loop we are reading the bytes using the read() function of the FileInputStream, and we repeat this process until we reach end of file which is denoted by -1. and using the output stream we write the bytes into the file. Please note that just to show we have printed the bytes, and as byte is a type of integer representation, it results in number.

If you want to develop the Character counter part all you need to do is to change the Stream handler classes from FileInputStream to FileReader and FileOutputStream to FileWriter.


	FileReader fr = null;
        FileWriter fw = null;
        try{
            /*String curDir = System.getProperty("user.dir");
            System.out.println(curDir);*/
            fr = new FileReader("inputfile.txt");
            fw = new FileWriter("outfile.txt");
            int buffer;
            while((buffer = fr.read()) != -1){
                System.out.print(buffer);
                fw.write(buffer);
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }

you see, only change has been made to the handler objects the result and output will remain the same.

Note: we have use finally block to close the handlers to make sure handlers are properly closed after each use in any case. This is good for practice as well as security of the program.

You can also read the File line by line but for this you will need a buffer handler, because the FileReader or FileInputStream and their opposite classes directly access storage device with each character or byte repeating but on using BufferedReader we can get each line into a string and then we can operate on it.

see following program, we'll discuss about buffer in more detail after this program.


package IO;
import java.io.*;
public class ReadLines {
    public static void main(String[] args) throws IOException {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("inputfile.txt"));
            String s;
            while ((s = br.readLine()) != null) {
                System.out.println(s);
            }
        } finally {
            if (br != null) {
                br.close();
            }
        }
    }
}

line one in input file.
line two in input file.
line three in input file.
last line in input file.

In this program we have used BufferedReader to wrap the FileReader this will provide the buffer support along with the character stream support.

Now as we said we'll explain more about the buffer, so read on. The buffer is a temporary space which takes in more than one unit of input or output before passing it in or out of a program. The buffering is useful to speed up the programs a little bit as it reduce the storage media access by each unit to each flush.

Flush is the process which reads in or write the data from buffer to storage media or program, when buffer fills up. You can do manual flushing or you can depend upon the auto-flusing for JVM. When we close the handler in finally block it also flushes the data from buffer before closing the handler.