【问题标题】:Java ProcessBuilder - get Output immediatelyJava ProcessBuilder - 立即获取输出
【发布时间】:2023-03-24 10:05:01
【问题描述】:

我想在一个 JAVA 程序中执行一个 EXE 文件。

它工作正常,但我希望 EXE 的输出立即在我的 JAVA 程序的 textArea 中。

目前我在“ping”命令完全完成后得到输出(所以 JAVA 程序挂起大约 3 秒)。但我想立即得到结果...

我做错了什么?

    ProcessBuilder pb = new ProcessBuilder().command("C:\\Windows\\SysWOW64\\PING.EXE", "127.0.0.1");
    pb.redirectErrorStream(true);

    Process process = pb.start();

    InputStream processStdOutput = process.getInputStream();
    Reader r = new InputStreamReader(processStdOutput);
    BufferedReader br = new BufferedReader(r);
    String line;
    while ((line = br.readLine()) != null) {
//      System.out.println(line); // the output is here
        textArea.append(line);
    }

命令向后。

我想使用这个程序: https://iperf.fr/iperf-download.php

输出如下:

    Connecting to host 10.1.100.34, port 5201
[  4] local 172.16.12.33 port 63802 connected to 10.1.100.34 port 5201
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-1.00   sec   112 MBytes   944 Mbits/sec                  
[  4]   1.00-2.00   sec   112 MBytes   944 Mbits/sec                  
[  4]   2.00-3.00   sec   112 MBytes   944 Mbits/sec                  
[  4]   3.00-4.00   sec   112 MBytes   940 Mbits/sec                  
[  4]   4.00-5.00   sec   112 MBytes   944 Mbits/sec                  
[  4]   5.00-6.00   sec   112 MBytes   944 Mbits/sec                  
[  4]   6.00-7.00   sec   112 MBytes   940 Mbits/sec                  
[  4]   7.00-8.00   sec   112 MBytes   944 Mbits/sec                  
[  4]   8.00-9.00   sec   112 MBytes   940 Mbits/sec                  
[  4]   9.00-10.00  sec   112 MBytes   944 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-10.00  sec  1.10 GBytes   942 Mbits/sec                  sender
[  4]   0.00-10.00  sec  1.10 GBytes   942 Mbits/sec                  receiver

iperf Done.

我仍然只有在 iperf 运行后才能得到这个完整的输出。如果我调试,我会得到这些行(逐行)。所以可能还有另一个问题......

【问题讨论】:

  • 可能是BufferedReader 中的缓冲区导致它被缓冲?
  • 不要使用BufferedReader这个,尝试直接从Reader r读取
  • 还有挂起是什么意思?你的意思是窗口弹出空白文本区域并在 3 秒后显示文本?你知道你必须为此使用线程吗?
  • 这可能是因为您不应该从另一个线程更新 Swing 组件。看看这个问题:stackoverflow.com/q/7229284/13075
  • @Henrik 已经在回答中

标签: java processbuilder


【解决方案1】:

确实,我尝试了您的示例,它立即输出流,但我没有使用文本区域,而是使用控制台输出。 您的代码究竟是如何被调用的?也许它与 GUI 重绘管理器有关 - 它是从 EDT 调用的吗?如果没有,这可能会导致延迟。

尝试做这样的事情:

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            area.append(line);
        }
    });

当您使用后台任务时(但您不知道),您应该为此使用名为 SwingWorker https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html 的专用实用程序。作为奖励,这里有完整的示例,您可以自己运行。它使用 Swing Worker 执行后台工作并在 EDT 上更新 GUI

public class LetsPing {

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new BorderLayout());
    frame.setSize(300, 300);
    frame.setLocationRelativeTo(null);

    JTextArea textArea = new JTextArea();
    frame.add(textArea, BorderLayout.CENTER);
    frame.setVisible(true);

    new SwingWorker<Void, String>() {
        @Override
        protected Void doInBackground() throws Exception {
            ProcessBuilder pb = new ProcessBuilder().command("C:\\Windows\\SysWOW64\\PING.EXE", "127.0.0.1");
            pb.redirectErrorStream(true);
            Process process;
            process = pb.start();
            InputStream processStdOutput = process.getInputStream();
            Reader r = new InputStreamReader(processStdOutput);
            BufferedReader br = new BufferedReader(r);
            String line;
            while ((line = br.readLine()) != null) {
                publish(line);
            }
            return null;
        }

        @Override
        protected void process(List<String> chunks) {
            for (String line : chunks) {
                textArea.append(line);
                textArea.append("\n");
            }
        }
    }.execute();
}
}

【讨论】:

  • 感谢您的代码。使用 ping 命令可以正常工作。但是当我使用像“iperf3.exe -c 10.15.100.34”这样的另一个命令时,我的行为与以前相同。在命令完成后,我只得到完整的输出。 (大约 4-5 秒)。
  • @Timo idk iperf3 的正常输出是什么,所以这里没有帮助。也许它对新行使用不同的字符集等。从使用普通阅读器而不是缓冲阅读器开始。
  • Ofc 因为 read 返回字符代码。但至少你现在知道缓冲是这里的问题。不要将代码传递给 cmets,因为它很难阅读。您可以编辑问题或其他内容。
  • int(实际上是char)创建String - String.valueOf((char)c);。它在小范围内很好,但不是在大范围内。
猜你喜欢
  • 2019-01-06
  • 2012-07-19
  • 1970-01-01
  • 1970-01-01
  • 2015-06-23
  • 2020-09-29
  • 2013-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多