从外部命令逐行处理无限输入

时间:2015-06-18 06:51:33

标签: java scala java-io

我有一个程序从外部命令读取输出并逐行处理。但是,当外部命令无限输出时(例如在无限循环中打印一些字符串),程序似乎被阻止并延迟 - 它会缓冲输出并在终止时完全打印所有内容。什么是处理来自另一个进程的无限数据输入的最佳方式,以便程序可以处理数据"同一时间"外在的是写作?是否有适用于此案例的高级API,我不需要使用监视器或其他并发内容?谢谢!我在Scala中编码,因此Scala和Java库都会有所帮助。这是Scala代码段。

val pb = new ProcessBuilder("./streamTest.py")
val p = pb.start()
val reader = new BufferedReader(new InputStreamReader(p.getInputStream()))
var line = reader.readLine()
while(line != null) {
  println(line)
  line = reader.readLine()
}
reader.close()

Java中的相同代码段:

ProcessBuilder pb = new ProcessBuilder("./streamTest.py");
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while(line != null) {
  System.out.println(line);
  line = reader.readLine();
}
reader.close();

这是一个不起作用的外部脚本streamTest.py的示例。如果我将命令更改为更简单的命令,例如&#34; ls -l&#34;,也就是说,让pb成为新的ProcessBuilder(&#34; ls -l&#34;),程序运行正常。< / p>

#! /usr/bin/python
import time
while True: 
    time.sleep(1)
    print("Hello World!")

2 个答案:

答案 0 :(得分:1)

你需要告诉Python不要缓冲输出。

可以采用以下解决方案。

手动冲洗

#! /usr/bin/python
import time
import sys
while True: 
    time.sleep(1)
    print("Hello World!")
    sys.stdout.flush()

更改stdout的缓冲模式

#! /usr/bin/python
import time
import sys
import os
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
while True: 
    time.sleep(1)
    print("Hello World!")

以无缓冲模式执行脚本

#! /usr/bin/python -u
import time
while True: 
    time.sleep(1)
    print("Hello World!")

ProcessBuilder pb = new ProcessBuilder("python", "-u", "./streamTest.py");

# set an environment variable before calling the Java application
export PYTHONUNBUFFERED=x

其他解决方案可能。

答案 1 :(得分:0)

System.out.print() 

方法没有刷新。因此你无法从其他java进程中读取它。你可以在print方法之后添加这行:

 System.out.flush();

或者你可以写

System.out.println("hello world");

因为println()方法按照Oracle documentation

中的说明自动刷新
  

可以创建PrintStream以便自动刷新;这意味着在写入字节数组,调用其中一个println方法,或者写入换行符或字节(&#39; \ n&#39;)之后,将自动调用flush方法。