我正在尝试编写一个程序,它启动 Windows 控制台 (cmd) 的进程并将输入、输出和错误流重定向到 System.in/out/err。此外,如果进程关闭(通过命令退出),我的程序应该关闭。
我已经写了一个解决方案,这很有效。唯一的问题是我使用的线程没有注意到进程已关闭。另外我不知道为所有这些流编写一个新线程是否是必要的,所以如果你知道一个更简单的解决方案来重定向流,我想听听。
这是我的SSCCE:
public class Main {
    public static boolean run = true;
    public static void main(String[] args) throws IOException {
        ProcessBuilder p = new ProcessBuilder("cmd");
        final Process pr = p.start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    pr.waitFor();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("test");
                run = false;
            }
        });
        // read(is);
        new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (run)
                    try {
                        write(System.in, pr.getOutputStream());
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (run)
                    try {
                        write(pr.getInputStream(), System.out);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                System.out.println("finish");
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (run)
                    try {
                        write(pr.getErrorStream(), System.err);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
            }
        }).start();
    }
    public static void write(InputStream is, OutputStream os)
            throws IOException {
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        if (len != -1) {
            byte[] data = new byte[len];
            for (int i = 0; i < len; i++) {
                data[i] = buf[i];
            }
            os.write(data);
            os.flush();
        }
    }
}
发生的情况是,我为每个流重定向创建一个新线程,并且重定向本身通过该write(inputStream,outputStream)方法发生。
但是我用来检查进程是否关闭的线程(pr.waitFor())并没有像我想象的那样工作。因此,如果 cmd 关闭,我不会注意到。
编辑2
好的,我只是忘了启动线程。但现在我能够接近这个问题。
System.in 重定向到 process.getOutputStream() 并没有注意到进程将要关闭。那是因为is.read(buf)是一种阻塞方法。因此,如果我尝试向 Process 写入新命令,那么它会注意到应该关闭流并完成程序。
如果有任何解决方案可以在没有线程的情况下重定向 Streams,我想以这种方式实现它。我认为这会更容易使用。