从进程打印Java InputStream

时间:2013-04-04 01:29:40

标签: java printing inputstream

UPDATE: I found a crucial part to why this probably isn't working! I used System.setOut(out); where out is a special PrintStream to a JTextArea

这是代码,但我遇到的问题是,只有在我结束流程后才打印出信息。

public Constructor() {
    main();
}

private void main() {
    btnStart.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            try {
                ProcessBuilder builder = new ProcessBuilder("java", textFieldMemory.getText(), "-jar", myJar);
                Process process = builder.start();
                InputStream inputStream = process.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream), 1);
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    System.out.println(line);
                }
                inputStream.close();
                bufferedReader.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    });
} 

当前输出:

Line 1
Line 2
Line 3
Line 4
Line 5

这是正确的输出,但是当我结束这个过程时它只被打印成一个大块。

有谁知道这是什么问题?如果是这样,你能帮我解释一下为什么会发生这种情况,请提前谢谢。

2 个答案:

答案 0 :(得分:9)

在单独的线程中处理进程的输出流可能会有所帮助。您还希望在继续逻辑之前明确等待进程结束:

ProcessBuilder builder = new ProcessBuilder("java",
        textFieldMemory.getText(), "-jar", myJar);
final Process process = builder.start();
final Thread ioThread = new Thread() {
    @Override
    public void run() {
        try {
            final BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
};
ioThread.start();

process.waitFor();

答案 1 :(得分:4)

基本上,从简单的信息来看,这听起来像是在执行流程并从事件调度线程中读取InputStream

任何阻止EDT的东西都会阻止它处理重绘请求,相反,你应该使用类似SwingWorker的东西,它具有允许你用EDT更新UI的功能。

请查看Concurrency in Swing了解详情

enter image description here

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class PBDemo {

    public static void main(String[] args) throws Exception {
        new PBDemo();
    }

    public PBDemo() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new BorderLayout());
            JTextArea ta = new JTextArea();
            add(new JScrollPane(ta));

            new ProcessWorker(ta).execute();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }

    public interface Consumer {
        public void consume(String value);            
    }

    public class ProcessWorker extends SwingWorker<Integer, String> implements Consumer {

        private JTextArea textArea;

        public ProcessWorker(JTextArea textArea) {
            this.textArea = textArea;
        }

        @Override
        protected void process(List<String> chunks) {
            for (String value : chunks) {
                textArea.append(value);
            }
        }

        @Override
        protected Integer doInBackground() throws Exception {
            // Forced delay to allow the screen to update
            Thread.sleep(5000);
            publish("Starting...\n");
            int exitCode = 0;
            ProcessBuilder pb = new ProcessBuilder("java.exe", "-jar", "HelloWorld.jar");
            pb.directory(new File("C:\\DevWork\\personal\\java\\projects\\wip\\StackOverflow\\HelloWorld\\dist"));
            pb.redirectError();
            try {
                Process pro = pb.start();
                InputConsumer ic = new InputConsumer(pro.getInputStream(), this);
                System.out.println("...Waiting");
                exitCode = pro.waitFor();

                ic.join();

                System.out.println("Process exited with " + exitCode + "\n");

            } catch (Exception e) {
                System.out.println("sorry" + e);
            }
            publish("Process exited with " + exitCode);
            return exitCode;
        }

        @Override
        public void consume(String value) {
            publish(value);
        }
    }

    public static class InputConsumer extends Thread {

        private InputStream is;
        private Consumer consumer;

        public InputConsumer(InputStream is, Consumer consumer) {
            this.is = is;
            this.consumer = consumer;
            start();
        }

        @Override
        public void run() {
            try {
                int in = -1;
                while ((in = is.read()) != -1) {
//                    System.out.print((char) in);
                    consumer.consume(Character.toString((char)in));
                }
            } catch (IOException exp) {
                exp.printStackTrace();
            }
        }
    }
}