Java PipedInputStream Class
Last modified: April 16, 2025
The java.io.PipedInputStream
class is a specialized input stream that
can be connected to a PipedOutputStream
. It creates a communication
pipe between two threads, allowing one thread to write data that another thread
can read.
PipedInputStream
is typically used for inter-thread communication.
The pipe has a limited buffer size, and writes will block if the buffer is full.
Similarly, reads will block if no data is available. Both streams must be
connected to work properly.
PipedInputStream Class Overview
PipedInputStream
extends InputStream
and provides
pipe-based input operations. It must be connected to a PipedOutputStream
either at construction or later. The default pipe size is 1024 bytes.
public class PipedInputStream extends InputStream { public PipedInputStream(); public PipedInputStream(int pipeSize); public PipedInputStream(PipedOutputStream src); public PipedInputStream(PipedOutputStream src, int pipeSize); public void connect(PipedOutputStream src); public synchronized int read(); public synchronized int read(byte[] b, int off, int len); public synchronized int available(); public void close(); }
The code above shows key methods provided by PipedInputStream
.
These methods allow for reading data from a connected output stream. The class
is thread-safe for concurrent access from multiple threads.
Creating a PipedInputStream
PipedInputStream can be created in several ways - with or without connection to a PipedOutputStream. The pipe size can be specified or left as default. Always ensure proper connection before use.
import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.IOException; public class Main { public static void main(String[] args) { try { // Create unconnected pipe PipedInputStream pis1 = new PipedInputStream(); // Create with default pipe size (connected) PipedOutputStream pos1 = new PipedOutputStream(); PipedInputStream pis2 = new PipedInputStream(pos1); // Create with custom pipe size (4KB) PipedOutputStream pos2 = new PipedOutputStream(); PipedInputStream pis3 = new PipedInputStream(pos2, 4096); System.out.println("Created three PipedInputStream instances"); pis1.close(); pis2.close(); pis3.close(); } catch (IOException e) { e.printStackTrace(); } } }
This example demonstrates different ways to create PipedInputStream. The first creates an unconnected pipe, while others connect during construction. Always close streams when done to release resources. The connected output streams are not automatically closed.
Basic Pipe Communication
This example shows the basic usage of PipedInputStream with PipedOutputStream. One thread writes data while another reads it. The pipe automatically handles synchronization between threads.
import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.IOException; public class Main { public static void main(String[] args) { try { PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos); // Writer thread new Thread(() -> { try { pos.write("Hello from pipe!".getBytes()); pos.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); // Reader thread new Thread(() -> { try { int data; while ((data = pis.read()) != -1) { System.out.print((char) data); } pis.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); } catch (IOException e) { e.printStackTrace(); } } }
This example demonstrates basic inter-thread communication using pipes. The writer thread sends data through PipedOutputStream. The reader thread receives it through PipedInputStream. Both streams must be properly closed after use.
Reading Bytes into an Array
For better performance, read multiple bytes at once into a byte array. This reduces method calls and improves efficiency. The read method returns the number of bytes actually read.
import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.IOException; public class Main { public static void main(String[] args) { try { PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos, 2048); // Writer thread new Thread(() -> { try { for (int i = 0; i < 100; i++) { pos.write(("Data " + i + "\n").getBytes()); } pos.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); // Reader thread new Thread(() -> { try { byte[] buffer = new byte[50]; int bytesRead; while ((bytesRead = pis.read(buffer)) != -1) { System.out.print(new String(buffer, 0, bytesRead)); } pis.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); } catch (IOException e) { e.printStackTrace(); } } }
This example shows bulk reading from a pipe into a byte array. The writer sends 100 lines of data. The reader processes data in chunks of 50 bytes. The pipe size is set to 2048 bytes to accommodate larger data transfers.
Checking Available Bytes
The available method returns the number of bytes that can be read without blocking. This is useful for checking if data is ready to be read from the pipe.
import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.IOException; public class Main { public static void main(String[] args) { try { PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos); // Writer thread new Thread(() -> { try { System.out.println("Writer: Sending data..."); pos.write("Sample data".getBytes()); Thread.sleep(2000); // Simulate delay pos.write("More data".getBytes()); pos.close(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } }).start(); // Reader thread new Thread(() -> { try { while (true) { int available = pis.available(); if (available > 0) { byte[] data = new byte[available]; pis.read(data); System.out.println("Reader: Got " + new String(data)); } if (available == -1) break; Thread.sleep(500); } pis.close(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } }).start(); } catch (IOException e) { e.printStackTrace(); } } }
This example demonstrates checking available bytes in the pipe. The writer sends data in two parts with a delay. The reader periodically checks for available data. This approach is useful when you want to avoid blocking reads.
Connecting Streams After Creation
PipedInputStream can be connected to PipedOutputStream after creation using the connect method. Both streams must be unconnected when calling this method.
import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.IOException; public class Main { public static void main(String[] args) { try { PipedInputStream pis = new PipedInputStream(); PipedOutputStream pos = new PipedOutputStream(); // Connect them after creation pis.connect(pos); // Writer thread new Thread(() -> { try { pos.write("Data sent through connected pipes".getBytes()); pos.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); // Reader thread new Thread(() -> { try { int data; while ((data = pis.read()) != -1) { System.out.print((char) data); } System.out.println(); pis.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); } catch (IOException e) { e.printStackTrace(); } } }
This example shows how to connect streams after creation. The connect method establishes the pipe between existing streams. Both streams must be in an unconnected state for this to work. The communication works the same as with constructor-based connection.
Handling Pipe Disconnection
When a pipe is broken (writer closes without reader finishing), an IOException occurs. Proper error handling ensures robust inter-thread communication.
import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.IOException; public class Main { public static void main(String[] args) { try { PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos); // Writer thread (closes immediately) new Thread(() -> { try { pos.write("Partial data".getBytes()); pos.close(); // Closes before reader finishes } catch (IOException e) { e.printStackTrace(); } }).start(); // Reader thread (slow reader) new Thread(() -> { try { Thread.sleep(1000); // Delay reading int data; while ((data = pis.read()) != -1) { System.out.print((char) data); Thread.sleep(500); // Slow processing } pis.close(); } catch (IOException | InterruptedException e) { System.err.println("Pipe error: " + e.getMessage()); } }).start(); } catch (IOException e) { e.printStackTrace(); } } }
This example demonstrates pipe disconnection handling. The writer closes before the reader finishes processing. The reader gets an IOException when trying to read from the broken pipe. Proper error handling prevents application crashes.
Source
Java PipedInputStream Class Documentation
In this article, we've covered the essential methods and features of the Java PipedInputStream class. Understanding these concepts is crucial for working with inter-thread communication in Java applications.
Author
List all Java tutorials.