In Java, an I/O Stream represents an input source or an output destination. A stream can represent many different kinds of sources and destinations, including disk files, devices, other programs, and memory arrays. Streams support many different kinds of data, including simple bytes, primitive data types, localized characters, and objects.
Think of a stream as a water pipe. Input Stream is the pipe bringing water (data) into your house (program). Output Stream is the pipe taking water (data) out of your house to the garden (file/network).
In Java, all I/O is performed by moving data through these "pipes." The java.io package contains nearly every class you might ever need to perform input and output (I/O) in Java.
Java defines two types of streams based on the type of data they handle. Understanding the difference is crucial for preventing data corruption (especially with special characters or emojis).
Used to handle input and output of raw bytes. All byte stream classes are descended from InputStream and OutputStream.
Use Case: Images, audio, video, and any non-text files.
Used to handle input and output of characters. They automatically handle Unicode (internationalization). All character stream classes descend from Reader and Writer.
Use Case: Text files, CSVs, and logs.
To read data, you choose an implementation of the abstract InputStream class. Here are the most common ones:
To send data out, you use an implementation of OutputStream:
System.out is actually a PrintStream).Since images are binary data, we must use Byte Streams (FileInputStream and FileOutputStream). Character Streams would corrupt the image data.
One of the most powerful features of Java I/O is the ability to chain streams together to add functionality. For example, you can wrap a FileInputStream inside a BufferedInputStream for speed, and then wrap that inside a DataInputStream to read Java primitives directly.
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("data.bin")));
If you want to save the entire state of a Java Object to a file, you use Serialization. The class must implement the Serializable interface. You use ObjectOutputStream to write the object and ObjectInputStream to read it back.
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"));oos.writeObject(myUserObject);
Q: What is the difference between Reader/Writer and InputStream/OutputStream?
A: Reader/Writer are character-oriented (16-bit) and handle Unicode/Text. InputStream/OutputStream are byte-oriented (8-bit) and handle raw data like images.
Q: What is a Buffered Stream and why should we use it?
A: Buffered streams read/write data in chunks rather than one byte at a time. This reduces the number of calls to the Operating System, which makes the code significantly faster.
Q: What are the three standard streams in Java?
A: System.in (Standard Input - Keyboard), System.out (Standard Output - Console), and System.err (Standard Error - Console).
I/O Streams are the nervous system of Java applications. While modern APIs like NIO.2 (which we covered in File Handling) are often easier to use, the underlying Stream architecture is what powers network communication, database connectivity, and complex data processing. Master the stream, and you master the data.
Next: Java Object Serialization →