ZetCode

Java OutputStream Class

Last modified: April 16, 2025

The java.io.OutputStream class is an abstract superclass representing an output stream of bytes. It provides the fundamental methods needed for writing data to various output destinations. All output stream classes inherit from this base class.

OutputStream defines the basic interface for byte output operations. Concrete subclasses implement these methods for specific destinations like files, network connections, or memory buffers. The class is part of Java's core I/O system.

OutputStream Class Overview

OutputStream is an abstract class that cannot be instantiated directly. It provides the template for all byte output operations in Java. Key methods include writing bytes, flushing buffers, and closing the stream.

public abstract class OutputStream implements Closeable, Flushable {
    public abstract void write(int b) throws IOException;
    public void write(byte[] b) throws IOException;
    public void write(byte[] b, int off, int len) throws IOException;
    public void flush() throws IOException;
    public void close() throws IOException;
}

The code above shows the key methods provided by OutputStream. These methods must be implemented by concrete subclasses. The class implements Closeable and Flushable interfaces for resource management.

Writing a Single Byte

The most basic operation is writing a single byte to the output stream. The write(int b) method writes the lowest 8 bits of the integer argument. Higher bits are ignored. This is an abstract method that subclasses must implement.

Main.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            
            // Write individual bytes
            os.write(72);  // H
            os.write(101); // e
            os.write(108); // l
            os.write(108); // l
            os.write(111); // o
            
            System.out.println("Bytes written successfully");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

This example demonstrates writing individual bytes to a file. The try-with-resources statement ensures the stream is closed properly. Each write call outputs one byte to the stream. The bytes represent ASCII characters for "Hello".

Writing Byte Arrays

For better performance, you can write multiple bytes at once using byte arrays. The write(byte[] b) method writes all bytes in the array. There's also a version that writes a portion of the array.

Main.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            
            // Create byte array
            byte[] data = "Hello, OutputStream!".getBytes();
            
            // Write entire array
            os.write(data);
            
            // Write portion of array
            byte[] largeData = new byte[100];
            System.arraycopy(data, 0, largeData, 0, data.length);
            os.write(largeData, 0, data.length);
            
            System.out.println("Byte arrays written successfully");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

This example shows two ways to write byte arrays. First, the entire array is written. Then, a portion of a larger array is written. The System.arraycopy method is used to copy data into the larger array. This approach is more efficient than writing individual bytes.

Flushing the Output Stream

The flush method forces any buffered output bytes to be written out. Some output streams implement buffering for performance. Flushing ensures data is actually written to the destination rather than sitting in a buffer.

Main.java
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try (OutputStream os = new BufferedOutputStream(
                new FileOutputStream("output.txt"))) {
            
            os.write("Important data".getBytes());
            
            // Force write to disk
            os.flush();
            
            System.out.println("Data written and flushed");
            
            // More writes
            os.write("More data".getBytes());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

This example demonstrates flushing a buffered output stream. The flush call ensures the data is written to disk immediately. Without flushing, data might remain in memory buffers until the stream is closed or the buffer fills. Flushing is important for critical data.

Closing the Output Stream

The close method releases system resources associated with the stream. It's crucial to close streams to prevent resource leaks. The try-with-resources statement automatically closes streams when the block exits.

Main.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        OutputStream os = null;
        try {
            os = new FileOutputStream("output.txt");
            os.write("Test data".getBytes());
            System.out.println("Data written successfully");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                    System.out.println("Stream closed");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

This example shows manual stream closing in a finally block. The stream is created outside try-with-resources to demonstrate proper manual closing. In practice, try-with-resources is preferred. Closing a stream automatically flushes any buffered data.

Using OutputStream with Buffering

For better performance, OutputStream is often wrapped with BufferedOutputStream. This reduces the number of physical write operations by buffering data in memory. The buffer is automatically flushed when full or when the stream is closed.

Main.java
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try (OutputStream os = new BufferedOutputStream(
                new FileOutputStream("largefile.dat"), 8192)) {
            
            // Write 1MB of data
            byte[] data = new byte[1024]; // 1KB buffer
            for (int i = 0; i < 1024; i++) { // 1024 * 1KB = 1MB
                os.write(data);
            }
            
            System.out.println("1MB of data written with buffering");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

This example demonstrates writing large amounts of data with buffering. The BufferedOutputStream uses an 8KB buffer (default is 8KB, but we explicitly set it). Writing many small chunks is more efficient with buffering. The buffer size can be tuned based on performance requirements.

Source

Java OutputStream Class Documentation

In this article, we've covered the essential methods and features of the Java OutputStream class. Understanding these concepts is crucial for working with output operations in Java applications.

Author

My name is Jan Bodnar, and I am a dedicated programmer with many years of experience in the field. I began writing programming articles in 2007 and have since authored over 1,400 articles and eight e-books. With more than eight years of teaching experience, I am committed to sharing my knowledge and helping others master programming concepts.

List all Java tutorials.