Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to copy input/output streams of the Process to their System counterparts?

This is a follow up to this question. The answer suggested there is

to copy the Process out, err, and input streams to the System versions

with IOUtils.copy as follows (after fixing various compilation errors):

import org.apache.commons.io.IOUtils;
import java.io.IOException;

public class Test {
    public static void main(String[] args)
            throws IOException, InterruptedException {
        final Process process = Runtime.getRuntime().exec("/bin/sh -i");
        new Thread(new Runnable() {public void run() {
            try {
                IOUtils.copy(process.getInputStream(), System.out);
            } catch (IOException e) {}
        } } ).start();
        new Thread(new Runnable() {public void run() {
            try {
                IOUtils.copy(process.getErrorStream(), System.err);
            } catch (IOException e) {}
        } } ).start();
        new Thread(new Runnable() {public void run() {
            try {
                IOUtils.copy(System.in, process.getOutputStream());
            } catch (IOException e) {}
        } } ).start();
        process.waitFor();
    }
}

However, the resulting code doesn't work for interactive processes like the one executing sh -i command. In the latter case there is no response to any of the sh commands.

So my question is: could you suggest an alternative to copy the streams that will work with interactive processes?

like image 661
vitaut Avatar asked Nov 14 '10 13:11

vitaut


People also ask

Which package is used for input and output streams?

The java.io package contains nearly every class you might ever need to perform input and output (I/O) in Java. All these streams represent an input source and an output destination. The stream in the java.io package supports many data such as primitives, object, localized characters, etc.

What is input stream and output stream explain them with example?

An input stream is used to read data from the source. And, an output stream is used to write data to the destination. For example, in our first Hello World example, we have used System. out to print a string.


1 Answers

The problem is that IOUtil.copy() is running while there is data in the InputStream to be copied. Since your process only produces data from time to time, IOUtil.copy() exits as it thinks there is no data to be copied.

Just copy data by hand and use a boolean to stop the thread form outside:

byte[] buf = new byte[1024];
int len;
while (threadRunning) {  // threadRunning is a boolean set outside of your thread
    if((len = input.read(buf)) > 0){
        output.write(buf, 0, len);
    }
}

This reads in chunks as many bytes as there are available on inputStream and copies all of them to output. Internally InputStream puts thread so wait() and then wakes it when data is available.
So it's as efficient as you can have it in this situation.

like image 117
Peter Knego Avatar answered Oct 19 '22 20:10

Peter Knego