我有一个程序,我在其中调用另一个单独的程序来完成一些工作(让我们称之为子流程),子流程需要一些时间来完成每个任务并在简单的控制台中显示进度。
问题是,当我尝试使用BufferedReader读取该控制台时,我自己的程序在写入TextArea中的每一行之前等待子进程完成。
这是我用来阅读每一行的代码:
JTextArea report = new JTextArea(20,40);
report.setText("");
try
{
Process p = new ProcessBuilder(command).start();
p.waitFor();
BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while(line!=null)
{
report.append(line+"\n");
line=reader.readLine();
}
}
catch(IOException e1){ error.setText("Failed to run toxpack");}
catch(InterruptedException e2) {error.setText("Failed to run command");}
我试图查看线程,但它仍然无效。
如何阅读每一行并将其添加到textArea中,而无需等待整个子流程完成。
编辑:添加了其余的代码,但我不确定它是否有用。 我想说的是,我希望子流程输出的每一行都出现在我的textArea中。没有等待它完成。
答案 0 :(得分:0)
您应该创建另一个从该进程读取的线程,并更新Swing组件:
final Process p = new ProcessBuilder("cat", "/etc/hosts").start();
final BufferedReader br = new BufferedReader(new InputStreamReader(
p.getInputStream()));
final Runnable r = new Runnable() {
@Override
public void run() {
try {
try {
for (String line = br.readLine(); line != null; line = br
.readLine()) {
final String l = line;
System.out.println(l);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
textArea.setText(textArea.getText() + "\n" + l);
}
});
Thread.sleep(50);
}
} finally {
br.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
final Thread t = new Thread(r);
t.start();
现在在阅读器线程中连续读取行,并且使用EventQueue.invokeLater
将Swing的更新发布到Swing的事件队列中,因为在Swing的事件调度线程中没有完成读取(详情:{{3} })。
sleep
只是为了减慢速度(模拟缓慢流动的数据)。
与
一起public class TextAreaDemo {
public static void main(String[] args) {
final JTextArea textArea = new JTextArea(60, 5);
final JScrollPane sp = new JScrollPane(textArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS) {
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 300);
}
};
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(sp);
frame.pack();
frame.setVisible(true);
// Add the reader snippet here
}
}
它将更新文本区域中的值。
答案 1 :(得分:-1)
这里有两个可能的问题:
1)如果其他进程没有写入整行,那么显然没有可以从输入流中读取的行。在这种情况下,readLine
方法会等到它有一个整行(在该过程完成后可能为真)。
2)更有可能:另一个进程写入缓冲写入器,但不刷新其内容。这导致在流程结束时刷新buffere。如果其他进程是Java进程,那么使用PrintWriter
将是最佳选择。 PrintWriter
应该以这种方式构建:
PrintWriter writer = new PrintWriter(..., true)
true
参数启用此打印编写器的自动刷新行为。请参阅PrintWriter文档。
修改
我刚看到p.waitFor()
电话。这会导致您的线程真正等到另一个进程完成。只需删除该行。