Java PipedReader Class
Last modified: April 16, 2025
The java.io.PipedReader
class is a character stream that reads from
a pipe. It must be connected to a PipedWriter
to form a pipe. Data
written to the PipedWriter
can be read from the PipedReader
.
PipedReader
is typically used for communication between threads.
The pipe provides a way for one thread to send data to another thread. The pipe
has a fixed-size buffer, and operations block when the buffer is full or empty.
PipedReader Class Overview
PipedReader
extends Reader
and provides character-based
pipe reading functionality. Key methods include read operations and connection
management. The class is not thread-safe for concurrent access by multiple readers.
public class PipedReader extends Reader { public PipedReader(); public PipedReader(int pipeSize); public PipedReader(PipedWriter src); public PipedReader(PipedWriter src, int pipeSize); public void connect(PipedWriter src); public synchronized int read(); public synchronized int read(char[] cbuf, int off, int len); public synchronized void close(); }
The code above shows key methods provided by PipedReader
. These
methods allow reading characters from a pipe connected to a PipedWriter
.
The pipe size can be specified or use the default value (1024 characters).
Creating a PipedReader
PipedReader
can be created in several ways. You can create an
unconnected reader and connect it later, or create it already connected to a
writer. The pipe size affects how much data can be buffered between threads.
import java.io.PipedReader; import java.io.PipedWriter; import java.io.IOException; public class Main { public static void main(String[] args) { try { // Create unconnected PipedReader PipedReader reader1 = new PipedReader(); // Create with default pipe size (1024) PipedWriter writer1 = new PipedWriter(); PipedReader reader2 = new PipedReader(writer1); // Create with custom pipe size (2048) PipedWriter writer2 = new PipedWriter(); PipedReader reader3 = new PipedReader(writer2, 2048); System.out.println("Created three PipedReader instances"); reader1.close(); reader2.close(); reader3.close(); } catch (IOException e) { e.printStackTrace(); } } }
This example demonstrates different ways to create PipedReader
. The
first creates an unconnected reader. The second and third create connected
readers with default and custom pipe sizes. Always close readers when done to
release resources.
Basic PipedReader Usage
The simplest way to use PipedReader
is to connect it to a
PipedWriter
and read characters. The read operation blocks when no
data is available. This is useful for thread communication.
import java.io.PipedReader; import java.io.PipedWriter; import java.io.IOException; public class Main { public static void main(String[] args) { try { PipedWriter writer = new PipedWriter(); PipedReader reader = new PipedReader(writer); // Write data in a separate thread new Thread(() -> { try { writer.write("Hello from PipedWriter!"); writer.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); // Read data from the pipe int data; while ((data = reader.read()) != -1) { System.out.print((char) data); } System.out.println("\nReading complete"); reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
This example shows basic pipe communication between threads. The writer thread
sends data which the main thread reads. The read
method blocks
until data is available. The pipe automatically closes when the writer is closed.
Reading Characters into an Array
For better performance, read multiple characters at once into a char array. This reduces method calls and improves efficiency. The read method returns the number of characters actually read.
import java.io.PipedReader; import java.io.PipedWriter; import java.io.IOException; public class Main { public static void main(String[] args) { try { PipedWriter writer = new PipedWriter(); PipedReader reader = new PipedReader(writer, 4096); // 4KB buffer // Writer thread new Thread(() -> { try { String message = "This is a longer message demonstrating " + "bulk reading from a PipedReader. " + "Reading multiple characters at once is more efficient."; writer.write(message); writer.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); // Reader with buffer char[] buffer = new char[32]; int charsRead; while ((charsRead = reader.read(buffer)) != -1) { System.out.print(new String(buffer, 0, charsRead)); } System.out.println("\nBulk reading complete"); reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
This example demonstrates bulk reading into a char array. The pipe has a 4KB buffer size. The reader processes 32 characters at a time. The charsRead value indicates how many characters were actually read into the array.
Connecting PipedReader Later
PipedReader
can be created unconnected and connected to a writer
later. The connection must be established before any reading or writing occurs.
Attempting to use an unconnected pipe causes an IOException.
import java.io.PipedReader; import java.io.PipedWriter; import java.io.IOException; public class Main { public static void main(String[] args) { try { // Create unconnected reader PipedReader reader = new PipedReader(); // Create writer and connect later PipedWriter writer = new PipedWriter(); // Connect them (can also use writer.connect(reader)) reader.connect(writer); // Write data in a separate thread new Thread(() -> { try { writer.write("Connected after creation"); writer.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); // Read data int data; while ((data = reader.read()) != -1) { System.out.print((char) data); } System.out.println("\nReading from late-connected pipe complete"); reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
This example shows how to connect a PipedReader
after creation. The
connection can be made from either end. Once connected, the pipe works the same
as if it was connected at creation time. Only one connection can exist at a time.
Handling Pipe Buffer Full Condition
When the pipe buffer is full, write operations block until space becomes available. Similarly, read operations block when the buffer is empty. This behavior is important for proper thread coordination.
import java.io.PipedReader; import java.io.PipedWriter; import java.io.IOException; public class Main { public static void main(String[] args) { try { // Small pipe buffer (10 chars) PipedWriter writer = new PipedWriter(); PipedReader reader = new PipedReader(writer, 10); // Writer thread that writes more than buffer can hold Thread writerThread = new Thread(() -> { try { for (int i = 0; i < 20; i++) { writer.write('A' + (i % 26)); System.out.println("Wrote: " + (char)('A' + (i % 26))); } writer.close(); } catch (IOException e) { e.printStackTrace(); } }); // Slow reader thread Thread readerThread = new Thread(() -> { try { for (int i = 0; i < 20; i++) { Thread.sleep(200); // Slow reading char c = (char) reader.read(); System.out.println("Read: " + c); } } catch (Exception e) { e.printStackTrace(); } }); writerThread.start(); readerThread.start(); writerThread.join(); readerThread.join(); reader.close(); } catch (Exception e) { e.printStackTrace(); } } }
This example demonstrates pipe blocking behavior. The writer will block when the 10-character buffer fills up. The slow reader gradually consumes data, allowing the writer to continue. This shows how pipes naturally synchronize producer and consumer threads.
Source
Java PipedReader Class Documentation
In this article, we've covered the essential methods and features of the Java PipedReader class. Understanding these concepts is crucial for implementing inter-thread communication using character streams in Java applications.
Author
List all Java tutorials.