Java Runtime.getRuntime():获取执行命令行程序的输出
我正在使用运行时从 Java 程序运行命令提示符命令。但是,我不知道如何获取命令返回的输出。
这是我的代码:
Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-send" , argument};
Process proc = rt.exec(commands);
我尝试执行 System.out.println(proc);
但没有返回任何内容。该命令的执行应返回两个用分号分隔的数字。我怎样才能将其放入变量中以进行打印?
这是我现在使用的代码:
String[] commands = {"system.exe", "-get t"};
Process proc = rt.exec(commands);
InputStream stdIn = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdIn);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<OUTPUT>");
while ((line = br.readLine()) != null)
System.out.println(line);
System.out.println("</OUTPUT>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
但是我没有得到任何输出,但是当我自己运行该命令时,它工作正常。
I'm using the runtime to run command prompt commands from my Java program. However, I'm not aware of how I can get the output the command returns.
Here is my code:
Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-send" , argument};
Process proc = rt.exec(commands);
I tried doing System.out.println(proc);
but that did not return anything. The execution of that command should return two numbers separated by a semicolon. How could I get this in a variable to print out?
Here is the code I'm using now:
String[] commands = {"system.exe", "-get t"};
Process proc = rt.exec(commands);
InputStream stdIn = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdIn);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<OUTPUT>");
while ((line = br.readLine()) != null)
System.out.println(line);
System.out.println("</OUTPUT>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
But I'm not getting anything as my output, but when I run that command myself it works fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
方法如下:
阅读 Javadoc 了解更多详细信息
Here is the way to go:
Read the Javadoc for more details here.
ProcessBuilder
would be a good choice to use.更快的方法是这样的:
这基本上是这个问题的浓缩版本:
我知道这个问题很旧,但我发布这个答案是因为我认为这可能会更快。
编辑(适用于 Java 7 及更高版本)
需要关闭 Streams 和 Scanner。使用 AutoCloseable 来获得简洁的代码:
A quicker way is this:
Which is basically a condensed version of this:
I know this question is old but I am posting this answer because I think this may be quicker.
Edit (For Java 7 and above)
Need to close Streams and Scanners. Using AutoCloseable for neat code:
如果类路径上已经有 Apache commons-io 可用,您可以使用:
If use are already have Apache commons-io available on the classpath, you may use:
在撰写本文时,包含代码的所有其他答案都可能导致死锁。
进程的
stdout
和stderr
输出缓冲区有限。如果您不同时听它们,那么当您尝试阅读另一个时,其中一个会被填满。例如,当进程等待写入stderr
时,您可能正在等待从stdout
读取数据。您无法从stdout
缓冲区中读取数据,因为它是空的,并且进程无法写入stderr
缓冲区,因为它已满。你们彼此永远等待着对方。这是一种读取进程输出而不存在死锁风险的可能方法:
关键是使用 ProcessBuilder.redirectErrorStream(true) ,它将把 stderr 重定向到
stderr 。代码>stdout
流。这允许您读取单个流,而无需在stdout
和stderr
之间交替。如果您想手动实现此操作,则必须使用两个不同线程中的流以确保永远不会阻塞。At the time of this writing, all other answers that include code may result in deadlocks.
Processes have a limited buffer for
stdout
andstderr
output. If you don't listen to them concurrently, one of them will fill up while you are trying reading the other. For example, you could be waiting to read fromstdout
while the process is waiting to write tostderr
. You cannot read from thestdout
buffer because it is empty and the process cannot write to thestderr
buffer because it is full. You are each waiting on each other forever.Here is a possible way to read the output of a process without a risk of deadlocks:
The key is to use
ProcessBuilder.redirectErrorStream(true)
which will redirectstderr
into thestdout
stream. This allows you to read a single stream without having to alternate betweenstdout
andstderr
. If you want to implement this manually, you will have to consume the streams in two different threads to make sure you never block.我们还可以使用流来获取命令输出:
Also we can use streams for obtain command output:
@Senthil 和 @Arend 的回答 (https://stackoverflow.com/a/5711150/2268559) 提到了
ProcessBuilder
。以下是使用 ProcessBuilder 并指定命令的环境变量和工作文件夹的示例:@Senthil and @Arend answer (https://stackoverflow.com/a/5711150/2268559) mentioned
ProcessBuilder
. Here is the example usingProcessBuilder
with specifying environment variables and working folder for the command:如果你用 Kotlin 编写,你可以使用:
If you write on Kotlin, you can use:
创建类:
}
并使用:
Create class :
}
and use:
为了可靠地启动子进程,您需要同时处理输出流,否则当 STDOUT 或 STDERR 填充到默认缓冲区限制时未使用它们时,进程将阻塞。
您可以通过这些测试命令来演示此问题,这些命令以相同的速度将大量数据写入 STDOUT 和 STDERR。如果您的应用程序无法跟上从这两个流的读取,则子进程将冻结/死锁:
您可以通过使用 ProcessBuilder 来避免该问题,它可以更好地控制输出流的去向,并通过调用
pb.redirectErrorStream(true)
或pb.inheritIO()
或使用pb.redirectErrorStream(true)
或将 STDOUT / STDERR 重定向到File
来防止死锁情况code>pb.redirectOutput/Error(file) / 或使用不同的线程从 STDOUT 和 STDERR 读取。下面是一个简单的示例,说明如何处理启动,它可以用来代替 Runtime.exec() 并将 STDOUT(/STDERR) 发送到您传入的任何流,从而避免死锁情况:
To reliably start a sub-process you need to handle the output streams at same time or the process will block when either STDOUT or STDERR is not consumed when they fill to the default buffer limit.
You can demonstrate this issue by these test commands which write large amount of data to STDOUT and STDERR at same pace. If your app does not keep up with reading from both of these streams then the sub-process will freeze / deadlock:
You can can avoid the problem by using
ProcessBuilder
which gives better control of where output streams go, and prevent deadlock situation by callingpb.redirectErrorStream(true)
orpb.inheritIO()
or redirect either of STDOUT / STDERR toFile
usingpb.redirectOutput/Error(file)
/ or use different threads for reading from STDOUT and STDERR.Here is a simple example of how to handle launch which could be used in place of
Runtime.exec()
and sends STDOUT(/STDERR) to any stream you pass in, and which avoids the deadlock situation:尝试读取运行时的
InputStream
:如果进程正在打印错误输出,您可能还需要读取错误流 (
proc.getErrorStream()
)。如果使用 ProcessBuilder,则可以将错误流重定向到输入流。Try reading the
InputStream
of the runtime:You might also need to read the error stream (
proc.getErrorStream()
) if the process is printing error output. You can redirect the error stream to the input stream if you useProcessBuilder
.改编自之前的答案:
Adapted from the previous answer:
与此页面上的其他片段几乎相同,但只是通过函数组织内容,我们开始......
类函数:
Pretty much the same as other snippets on this page but just organizing things up over an function, here we go...
The Class function: