1

我正在尝试编写一个程序,它启动 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,我想以这种方式实现它。我认为这会更容易使用。

4

2 回答 2

2

主要问题是你没有.start在线程上做,但我也想提出改进建议

等待主线程中的进程:

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();

        // 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();


             try {
                 pr.waitFor();
             } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
             System.out.println("test");
             run = false;

    }

    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();
        }

    }
}
于 2013-09-10T06:53:54.023 回答
0

我猜那是因为您的主线程可能在所有这些线程完成之前退出。尝试pr.waitFor()在 main 函数的末尾添加。

于 2013-09-10T06:50:15.950 回答