dcsimg
November 15, 2018
Hot Topics:

Understanding Byte Streams and Character Streams in Java

  • April 30, 2018
  • By Manoj Debnath
  • Send Email »
  • More Articles »

Java performs I/O operations through an abstraction called a stream. There are two basic types of stream defined by Java, called byte stream and character stream. The byte stream classes provide a convenient means for handling input and output of bytes and character streams provide a convenient means for handling input and output of characters, respectively. This article elaborates on these two concepts of stream handling in Java.

Stream Overview

From the perspective of Java, "stream" essentially refers to an abstraction that is used to produce and consume flow of sequential information. The flow of information can be a result of input or output operations performed on any physical device linked to Java I/O subsystem. The actual linked devices may vary, such as a local storage device or network. But, the underlying principle remains the same. Typically, Java stream supports a variety of devices, like a keyboard, network socket, disk file, and so forth. Hence, it provides a convenient way to handle I/O operation in the same way for different types of devices it is actually linked to. The steam classes are bundled in the java.io package.

Note that Java 8 introduced a different type of streams bundled in the java.nio package which have more interesting uses. Let's not delve into that here; instead, let's focus on the basic stream classes provided in the java.io package. If you are still interested, refer to the article "Working with Java Stream API" for a glimpse of its uses.

Byte Streams and Character Streams

There are two types of streams in Java: byte and character. When an I/O stream manages 8-bit bytes of raw binary data, it is called a byte stream. And, when the I/O stream manages 16-bit Unicode characters, it is called a character stream. A Unicode set is basically a type of character set where each character corresponds to a specific numeric value within the given character set. Typically, every programming language adopts a particular character set to represent and manage its use of characters. Apart from Unicode, another commonly used character set is ASCII, defined by the International Standard Organization (ISO). At the inception of Java (version 1.0), it did not have character streams; therefore, all I/O operations were byte oriented. The character streams were introduced later (version 1.1). Note that the idea of character and byte streams should not be mixed with low-level I/O operation; they are always bit and bytes, after all. But, the point of character and byte streams essentially provides a convenient and efficient way to handle data streams in Java.

What's the Difference?

As mentioned earlier, the difference is simply for convenience. Some streams are inherently byte oriented and some are character oriented. As a result, it is always convenient to handle them with appropriate classes and methods defined in I/O stream package. For example, the FileOutputStream is meant for reading a raw stream of bytes, such as image data. Similarly, the FileOutputStream object may be used to write a raw byte stream. Under similar circumstances, reading and writing files based on character-oriented stream of data FileReader and FileWriter may be used, respectively. These classes provide specific methods to manipulate appropriate stream data.

The Byte Stream Classes

At the top of the byte stream class hierarchy, there are two abstract classes: InputStream for byte-oriented input and OutputStream for byte-oriented output operations. The hierarchical layout is as follows:

  • InputStream: Top level abstract class for byte-oriented input stream.
    • ByteArrayInputStream: An instance of this class contains an internal buffer to read bytes stream.
    • FilterInputStream: An instance of this class contains some other input stream as a basic source of data for further manipulation.
      • BufferedInputStream: This enables a FilterInputStream instance to make use of a buffer for input data.
      • DataInputStream: An instance of this class enables reading primitive Java types from an underlying input stream in a machine-independent manner.
      • LineNumberInputStream: An instance of this class aids in keeping track of the current line number of the input stream.
      • PushbackInputStream: This provides the ability to push back, or "unread," a data byte after reading it.
    • FileInputStream: An instance of this class is used to obtain input bytes from a file in a file system.
    • ObjectInputStream: An instance of this class is used to deserialize an object after it has been serialized by ObjectOutputSteam.
    • PipedInputStream: An instance of this class provides a pipe or buffer for an input byte that works in the FIFO manner.
    • SequenceInputStream: An instance of this class represents a logical concatenation of two or more input streams which are read in sequence, one after another.
  • OutputStream: Top-level abstract class for byte-oriented input stream.
    • ByteArrayOutputStream: An instance of this class contains an internal buffer to write a bytes stream.
    • FilterOutputStream: An instance of this class contains some other output stream as a basic source of data for further manipulation.
      • BufferedOutputStream: This enables a FilterOutputStream instance to make use of a buffer for output data.
      • DataOutputStream: An instance of this class enables writing primitive Java types to an underlying output stream in a machine-independent manner.
      • PrintStream: This empowers the OutputStream objects with the ability to print representations of various data values conveniently.
    • FileOutputStream: An instance of this class is used to output a stream for writing data to a file or to a file descriptor.
    • ObjectOutputStream: An instance of this class is used to serialize an object which can be deserialized with ObjectInputStream.
    • PipedOutputStream: An instance of this class provides a pipe or buffer for output byte that works in the FIFO manner.

Refer here for a quick byte stream example.

The Character Stream Classes

At the top of the character stream class hierarchy, there are two abstract classes: Reader for character-oriented input and Writer for character-oriented output operations. The hierarchical layout is as follows:

  • Reader: Top-level abstract class to read to character streams.
    • BufferedReader: Provides an in-between buffer for efficiency while reading text from character input stream.
      • LineNumberReader: Uses a buffered character input stream that keeps track of line numbers.
    • CharArrayReader: Implements an auto-increasing character buffer that may be used as a reader.
    • FilterReader: An instance of this class is used for reading character files.
      • PushbackReader: This enables a character to be pushed back into the stream after reading.
    • InputStreamReader: An instance of this class provides a bridge from byte streams to character streams. Bytes are decoded into characters using a specified character set.
      • FileReader: An instance of this class is used for reading character files.
    • PipedReader: Uses a pipe for character input stream.
    • StringReader: Character output stream reader from source string.
  • Writer: Top-level abstract class to write to character streams.
    • BufferedWriter: Provides an in-between buffer for efficiency while writing text to a character output stream.
    • CharArrayWriter: Implements an auto-increasing character buffer that may be used as a writer.
    • FilterWriter: Abstract class for writing filtered character streams.
    • OutputStreamWriter: An instance of this class provides a bridge between character streams and byte streams. Characters are encoded into bytes using a specified character set.
      • FileWriter: An instance of this class is used for writing character files.
    • PipedWriter: Uses a pipe for character output stream.
    • PrintWriter: Prints a formatted representation of an object to a test-output stream.
    • StringWriter: Character output stream is collected in a string buffer and may be used for constructing a string.

Refer here for a quick character stream example.

Predefined Streams

Java provides three predefined stream objects: in, out, and err, defined in the System class of the java.lang package. The out object refers to the standard output stream or console. The in object refers to standard input, which is the keyboard. And, the err object refers to a standard error, which again is nothing but the console. As should be obvious, they may be redirected to any other compatible I/O devices, because System.in is nothing but an object of InputStream, and System.out and System.err are objects of the PrintStream class. So, they basically work on a byte-oriented stream although we can use them for reading and writing characters to and from the console.

Here is a quick example.

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class TestStream{
   public static void main(String[] args) throws Exception{
      BufferedReader br=new BufferedReader(new
         InputStreamReader(System.in));
      System.out.println("Enter your name: ");
      String name=br.readLine();
      if(name.length()<=0)
         System.err.println("Name cannot be empty");
      else
         System.out.println("Hi! "+name);
   }
}

Conclusion

A Java stream acts as a file handling wrapper that operates according to the corresponding I/O constructs. In many cases, character-oriented stream classes and byte-oriented stream classes function in a very similar fashion. But, that does not mean that they are not different. The stream classes defined in the java.io packages are rather simple and unsophisticated, but they do serve their purpose. The new streams introduced with Java 8, on the other hand, are more sophisticated and have numerous interesting uses.

Reference

Java API Documentation






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap

Thanks for your registration, follow us on our social networks to keep up-to-date