我正在尝试在日志文件上写入输出或通过Runtime.getRuntime()。exec()启动的Java程序。我正在使用以下代码。
public class Thread_Write extends Thread {
int id;
public void run() {
try {
File log = new File("./log"+id+".txt");
log.createNewFile();
FileWriter fw = new FileWriter("./"+"log"+id+".txt",true);
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("java WriteToFile "+id);
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
fw.write(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public Thread_Write(int i) {
super();
this.id = i;
}
public static void main(String[] args) {
for (int i =0 ; i<10;i++) {
(new Thread_Write(i)).start();
}
}
}
“java WriteToFile id”假设在终端上写一个例外,但不幸的是,我没有得到任何东西。奇怪的是,如果我通过“echo test”更改此命令,将在日志文件的末尾正确添加“test”。知道为什么吗?
干杯。
答案 0 :(得分:2)
最有可能的原因是异常发生在错误流中。一种选择是重定向错误流:process.getErrorStream()
。
或者,您可以使用a ProcessBuilder:
ProcessBuilder pb = new ProcessBuilder("java", "WriteToFile", String.valueOf(id));
pb.redirectErrorStream(true);
pb.redirectOutput(log);
Process p = pb.start();
答案 1 :(得分:1)
process.getInputStream()
无法提供错误,您需要使用process.getErrorStream()
。另一种方法是首先使用processBuilder.redirectErrorStream(true)
。这将导致stdout和stderr在process.getInputStream()
上可用。
答案 2 :(得分:0)
这里有几个问题。以下是我将如何编写run()方法(基本原理):
public void run() {
try {
Process process = Runtime.getRuntime().exec("java WriteToFile " + id);
Thread err = consume(process.getErrorStream(),
new FileOutputStream("./" + "log" + id + ".txt"));
Thread std = consume(process.getInputStream(),
new FileOutputStream("./" + "log_stdout" + id + ".txt"));
err.join();
std.join();
} catch (Exception e) {
e.printStackTrace();
}
}
private Thread consume(final InputStream stream,
final OutputStream out) {
Thread result = new Thread() {
public void run() {
PrintWriter pw = new PrintWriter(out, true);
try (Scanner sc = new Scanner(stream)) {
while (sc.hasNext()) {
pw.println(sc.nextLine());
}
}
}
};
result.start();
return result;
}
(1)最重要的是:如果WriteToFile
写入stderr和stdout,你的进程将阻塞:因为它只从stderr读取,所以没有人从stdout缓冲区读取字节。一旦此缓冲区填满WriteToFile
将阻止下一个println()。假设在写入异常之前发生这种情况,两个进程都将陷入死锁状态,每个进程都在等待另一个进程进行第一次移动。解决方案:生成两个线程,一个用于消耗stdout,另一个用于消耗stderr。
其他(次要)问题:
(2)而不是将InputStream
包装在InputStreamReader
中,而BufferedReader
又包含在log
中,您可以使用Scanner类:它的构造函数可以使用InputStream,它会为您提供您需要的readLine()方法。
(3)如果在log.createNewFile();
中使用唯一目的,则无需创建FileWriter
变量 - 您的PrintWriter
对象将为您创建输出文件。 / p>
(4)您可能想要使用FileWriter
对象而不是println()
。前者为您提供{{1}},可让您逐行打印输出。