Streams: Basic I/O in Java

A stream represents a flow of data, or a channel of communication with a writer at one end and a reader at the other. To handle input and output we use java.io package. Let us discuss the classification of I/O streams.

Classification of I/O streams
  1. Byte Streams
  2. Character Streams
  3. Buffered Streams
  4. Terminal I/O or Console I/O
  5. Data Streams
  6. Object Streams
1. Byte Streams:

The byte streams are used to perform input and output of 8 – bit bytes. All byte stream classes are derived from InputStream and OutputStream

InputStream and OutputStream are abstract classes that define the lowest-level interface for all byte streams. They contain methods for reading or writing an unstructured sequence of bytes.
Java implements subclasses of these for activities such as reading from and writing to files. Because all byte streams inherit the structure of InputStream or OutputStream, the various kinds of byte streams can be used interchangeably. 

All the methods of this class will throw an IO Exception. Some of the byte streams are
 


2. Character Streams:

The Character Streams are used for reading or writing a sequence of character data, with support for Unicode. All other character streams in Java are built on top of Reader and Writer. Reader and Writer are very much like InputStream and OutputStream, except that they deal with characters instead of bytes. As true character streams, these classes correctly handle Unicode characters. InputStreamReader and OutputStreamWriter are special classes that use a character-encoding scheme to translate between character and byte streams.

All the methods of this class will throw an IO Exception. Some of the byte streams are




OutputStreamWriter


3. Buffered Streams:

A buffer can increase efficiency by reducing the number of physical read or write operations that correspond to read( ) or write( ) method calls. 

Java platform implements buffered I/O streams. Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.

Some of the buffered streams are

BufferedInputStream

BufferedOutputStream

BufferedReader

BufferedWriter

4. Terminal I/O or Console I/O

The terminal or console refers to command line environment or command prompt. The most commonly used standard output is System.out and System.err is derived from OutputStream object and standard input is System.in is derived from InputStream object. The following example shows the correspondence. 

        InputStream stdin = System.in;
        OutputStream stdout = System.out;
        OutputStream stderr = System.err;

System.out

System.out is the first instance of the OutputStream class most programmers encounter. Specifically, System.out is the static out field of the java.lang.System class. It's an instance of java.io.PrintStream, a subclass of java.io.OutputStream.

System.out corresponds to stdout in C. Normally; output sent to System.out appears on the console. As a general rule, the console converts the numeric byte data System.out sends to it into ASCII. Thus, the following lines write the string "Hello World!" on the console:
 
byte[] hello = {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 10,13};
 
System.out.write(hello);

Sytem.err

C programmers are familiar with stderr, which is commonly used for error messages. stderr is a separate file pointer from stdout, but often means the same thing. Generally, stderr and stdout both send data to the console, whatever that is. However, stdout and stderr can be redirected to different places. For instance, output can be redirected to a file while error messages still appear on the console.

System.err is Java's version of stderr. Like System.out, System.err is an instance of java.io.PrintStream, a subclass of java.io.OutputStream. System.err is most commonly used inside the catch clause of a TRy/catch block, as shown here:

try
{
  // Do something that may throw an exception.
}
catch (Exception ex) 
{
  System.err.println(ex);
}

System.in

System.in is the input stream connected to the console, much as System.out is the output stream connected to the console. In C terms, System.in is stdin and can be redirected from a shell in the same fashion. System.in is the static in field of the java.lang.System class. It's an instance of java.io.InputStream.

We can read a single byte at a time from standard input with the InputStream's read( ) method. If you look closely at the API, you'll see that the read( ) method of the base InputStream class is an abstract method. What lies behind System.in is a particular implementation of InputStream that provides the real implementation of the read( ) method:

    try 
{
        int val = System.in.read(  );
       } 
catch ( IOException e ) 
{
        ...
      }
 
The following example reads each byte from an input stream and prints its value:

    int val;
    try 
{
           while( (val=System.in.read(  )) != -1 )
            System.out.println((byte)val);
          } 
catch ( IOException e ) 
{ ... }

5. Data Streams

Data streams support binary I/O of primitive data type values such as boolean, char, byte, short, int, long, float, and double as well as String values. All data streams are derived from either the DataInput interface or the DataOutput interface. The Data Streams are shown below.

DataInputStream

DataOutputStream

DataInputStream and DataOutputStream are filter streams that let you read or write strings and primitive data types comprised of more than a single byte. DataInputStream and DataOutputStream implement the DataInput and DataOutput interfaces, respectively. These interfaces define methods for reading or writing strings and all of the Java primitive types, including numbers and Boolean values. DataOutputStream encodes these values in a machine-independent manner and then writes them to its underlying byte stream. DataInputStream does the converse.


6. Object Streams

Object streams support I/O of objects similarly, just as data streams support I/O of primitive data types.

The object stream classes are ObjectInputStream and ObjectOutputStream. These classes implement ObjectInput and ObjectOutput, which are subinterfaces of DataInput and DataOutput.  ObjectInputStream and ObjectOutputStream, are used to serialize primitive types and objects.