Java I/O Streams

Naveen AnamaneniUpdated · 5 min read

Java I/O (input and output) is the part of Java used to read data into a program and write data out of it: to and from files, the console, network connections and memory. The java.io package does this with streams. A stream is a sequence of data that flows in one direction, like water in a pipe: an input stream brings data into the program, and an output stream carries data out. (These I/O streams are a different idea from the java.util.stream streams used with collections.) In this lesson, you will learn the two kinds of I/O streams and when to use each.

Input and Output Streams

Input streams bring data in; output streams carry data out
  • An input stream reads data from a source: a file, the keyboard, a network socket, an array in memory.
  • An output stream writes data to a destination: a file, the screen, a socket, an array in memory.
  • Data in a stream is read or written in order, one piece after another.

Byte Streams vs Character Streams

Java has two families of streams:

Byte streamsCharacter streams
Unit of data8-bit bytes16-bit characters (char)
Base classesInputStream, OutputStreamReader, Writer
Use forBinary data: images, audio, ZIP files, any file copied as-isText: .txt, .csv, .java, .json files
Handles character encodingNoYes (UTF-8 and others)
Example classesFileInputStream, BufferedOutputStreamFileReader, BufferedWriter

Names make it easy to tell them apart: classes ending in Stream work with bytes, and classes ending in Reader or Writer work with characters.

The Three Standard Streams

Every Java program has three streams ready to use, in the System class:

StreamTypeConnected to
System.inInputStreamThe keyboard
System.outPrintStreamThe screen (normal output)
System.errPrintStreamThe screen (error messages)

Example: Writing and Reading a Text File

Let's see an example that writes two lines with a character stream and reads them back.

FirstIo.java▶ Try it
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class FirstIo {
    public static void main(String[] args) throws IOException {
        try (FileWriter out = new FileWriter("names.txt")) {
            out.write("Navika\n");
            out.write("Srihitha\n");
        }
 
        try (FileReader in = new FileReader("names.txt")) {
            int c;
            StringBuilder text = new StringBuilder();
            while ((c = in.read()) != -1) {
                text.append((char) c);
            }
            System.out.print(text);
        }
    }
}
Output
Navika
Srihitha

Explanation: FileWriter is a character output stream; it writes text to names.txt. FileReader reads it back one character at a time. read() returns -1 at the end of the file. Both streams are opened in try-with-resources, so they are closed automatically, even if an error occurs.

Example: Copying Bytes

ByteCopy.java▶ Try it
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class ByteCopy {
    public static void main(String[] args) throws IOException {
        try (FileOutputStream out = new FileOutputStream("data.bin")) {
            out.write(new byte[] {(byte) 0xCA, (byte) 0xFE, 0, 42});
        }
 
        int count = 0;
        try (FileInputStream in = new FileInputStream("data.bin")) {
            int b;
            while ((b = in.read()) != -1) {
                System.out.print(Integer.toHexString(b) + " ");
                count++;
            }
        }
        System.out.println("(" + count + " bytes)");
    }
}
Output
ca fe 0 2a (4 bytes)

Explanation: FileOutputStream writes raw bytes, and FileInputStream reads them back. Each read() returns one byte as a number from 0 to 255, or -1 at the end. The bytes aren't treated as text at all, which is exactly what binary data needs.

Common Mistakes

Using a Reader or Writer for images or ZIP files. Character conversion corrupts binary data; use byte streams.

Forgetting to close output streams. Buffered data may never reach the file.

Confusing I/O streams with the Stream API. They share a name but are unrelated.

Interview Corner

What is the difference between byte streams and character streams?

Byte streams, based on InputStream and OutputStream, read and write raw 8-bit bytes and are used for binary data such as images and archives. Character streams, based on Reader and Writer, read and write 16-bit characters and convert between bytes and characters using a character encoding such as UTF-8, so they're used for text. Classes ending in "Stream" are byte streams; classes ending in "Reader" or "Writer" are character streams.

Practice

  1. Easy: Write three of your favorite subjects to subjects.txt with FileWriter, then read the file back and print it.
  2. Harder: Count the number of bytes in a file using FileInputStream, then compare the result with Files.size(Path.of(...)).

Quick check: Java I/O

4 questions
1Which base classes handle text?
2Which stream type should copy an image file?
3What does read() return at the end of a stream?
4What type is System.out?

Key Takeaways

Was this tutorial helpful?

Lesson 341 of 482