febot
febot

Reputation: 158

How to use Piped IO Streams

From the documentation for PipedInputStream and PipedOutputStream, the former forms the receiving end of a communication pipe and the latter is the sending end. This forms a structure like this:
A -> PipedInputStream -> PipedOutputStream -> B
My question is how do I specify what A and B are. I would like A to be the standard input stream System.in and B to be a FileOutputStream.
Correct me if I am wrong, but I think the Piped Stream objects offer a way to connect an InputStream to an OutputStream. Yet I don't see any methods for connecting a PipedInputStream to anything other than a PipedOutputStream, and vice versa.

Upvotes: 2

Views: 3406

Answers (3)

areus
areus

Reputation: 2948

PipedInputStream and PipedOutputStream are used to create a pipe between two threads.

Usually you do something like:

  • Create a PipedOutputStream and a PipedInputStream and connect them
  • Start a thread that writes to PipedOutputStream
  • Start a thread that reads from PipedInputStream

Upvotes: 4

Andreas
Andreas

Reputation: 159086

You linked to the javadoc of PipedOutputStream, but it seems like you didn't read it.

A piped output stream can be connected to a piped input stream to create a communications pipe. The piped output stream is the sending end of the pipe. Typically, data is written to a PipedOutputStream object by one thread and data is read from the connected PipedInputStream by some other thread.

So, the data flows in the opposite direction from what the question shows:

Thread A  →  PipedOutputStream  →  PipedInputStream  →  Thread B

As you can see, I also clarified it by showing that A and B are threads, i.e. code, not other streams.


Correct me if I am wrong, but I think the Piped Stream objects offer a way to connect an InputStream to an OutputStream.

As you can see from the description above, you're wrong about that. Piped Stream objects offer a way for a thread to send data to another thread using Stream I/O calls.

They are called "piped" because it works similar to how one program can write to stdout, and another program can read from stdin, and you can then connect the two using a | pipe, e.g. foo.exe | bar.exe will pipe the output from the foo program as input to the bar program.

That's just between processes, while the Piped Streams are between threads.


I would like A to be the standard input stream System.in and B to be a FileOutputStream.

If you want to copy from System.in to a file, you can do any of the following:

// Using newer NIO.2 API (Java 7+)
Files.copy(System.in, Paths.get(filename), StandardCopyOption.REPLACE_EXISTING);
// Using old File I/O API with transferTo (Java 9+)
try (FileOutputStream out = new FileOutputStream(new File(filename))) {
    System.in.transferTo(out);
}
// Using old File I/O API with try-with-resources (Java 7+)
try (FileOutputStream out = new FileOutputStream(new File(filename))) {
    byte[] buf = new byte[8192];
    for (int len; (len = System.in.read(buf)) > 0; )
        out.write(buf, 0, len);
}
// Using old File I/O API (any Java version)
FileOutputStream out = new FileOutputStream(new File(filename));
try {
    byte[] buf = new byte[8192];
    for (int len; (len = System.in.read(buf)) > 0; )
        out.write(buf, 0, len);
} finally {
    out.close();
}

Upvotes: 5

Turamarth
Turamarth

Reputation: 2282

First of all the direction of communication is
A -> PipedOutputStream -> PipedInputStream -> B.

It is not possible to set A or B to some specific streams.
A simply represents a thread that calls the write() method of PipedOutputStream to submit some data, which is then transferred to the PipedInputStream from which another thread B can read it using the read() method.

Upvotes: 5

Related Questions