Windows控制台重定向

时间:2013-09-10 06:46:59

标签: java windows-console

我正在尝试编写一个程序,该程序启动Windows控制台(cmd)的进程,并将Input,Output和Errorstream重定向到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();
        }

    }
}

会发生什么,是我为流的每个重定向创建一个新的Thread,重定向本身通过write(inputStream,outputStream)方法发生。

但我用来检查进程是否已关闭(pr.waitFor())的线程并不像我想象的那样工作。因此,如果cmd关闭,我就不会被注意到。

EDIT2

好的,我只是忘了启动线程。但现在我能够接近这个问题了。

将System.in重定向到process.getOutputStream()并没有注意到该进程将被关闭。这是因为is.read(buf)是一种阻止方法。因此,如果我尝试向Process写一个新命令,那么它会注意到流应该被关闭并完成程序。

如果有任何解决方案可以在没有线程的情况下重定向Streams,我希望以这种方式实现它。我认为这会更容易使用。

2 个答案:

答案 0 :(得分: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();
        }

    }
}

答案 1 :(得分:0)

我猜这是因为你的主线程可以在所有这些线程完成之前退出。尝试在主要功能的末尾添加pr.waitFor()