获取Java中字符串的命令提示符输出
我需要一个java方法,该方法将读取命令提示符输出并将其存储到字符串中以读入java 到目前为止,这是我所拥有的,但不起作用获取Java中字符串的命令提示符输出,java,tostring,command-prompt,outputstream,Java,Tostring,Command Prompt,Outputstream,我需要一个java方法,该方法将读取命令提示符输出并将其存储到字符串中以读入java 到目前为止,这是我所拥有的,但不起作用 public void testGetOutput() { System.out.println("\n\n****This is the testGetOutput Method!****"); String s = null; String query = "dir " + this.desktop; try { Run
public void testGetOutput() {
System.out.println("\n\n****This is the testGetOutput Method!****");
String s = null;
String query = "dir " + this.desktop;
try {
Runtime runtime = Runtime.getRuntime();
InputStream input = runtime.exec("cmd /c " + query).getInputStream();
BufferedInputStream buffer = new BufferedInputStream(input);
BufferedReader commandResult = new BufferedReader(new InputStreamReader(buffer));
String line = "";
try {
while ((line = commandResult.readLine()) != null) {
s += line + "\n";
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}//end testGetOutput()
我认为问题在于,当我试图将查询更改为执行HandBrakeCLI.exe的命令时。当程序正在运行(但似乎已暂停)时,查看我的系统,它显示HandBrakeCLI.exe正在我的IDE下运行的cmd窗口下运行。所有这些都是有道理的,但是HandBrakeCLI.exe没有退出,所以我猜这就是为什么我不能将输出读取为程序的输入
所以,在这个背景之后。我的大问题是:如何在查询完成后关闭HandBrakeCLI.exe,以便获得其输出?
为了获得更多信息,上面的方法与我针对HandBrakeCLI的scan DVD方法之间的唯一区别是查询变量不同。像这个例子:
String query = "C:\Users\Kent\Desktop\HBCLI\HandBrakeCLI -t --scan -i "C:\Users\Kent\Desktop\General Conference DVDs\Sources\174th October 2004\DVD 1"; //this is actually a variable in the DVD object, but here's an example'
哦,顺便说一句,当我在常规命令提示符下运行该查询时,它完全按照我的要求执行,提供了我迫切需要的所有输出
这是最初的问题(我不知道如何重新提交问题):
我到处找都找不到。我不确定我的发现是否与我想做的事情有关。我还没有太多的代码,所以在这里放代码没什么用,我认为这应该很简单,所以我将在这里给出一些截图。所以我的任务是:
假设您使用
Runtime.exec()
启动外部进程,给您一个进程
对象,该对象上有三个相关方法:getOutputStream()
,getInputStream()
和getErrorStream()
我认为很容易对这些产生混淆——您可能认为您希望看到流程的输出,因此“输出流”就是您想要的。但您需要记住的是,这些对象的命名是从Java代码的角度进行的——OutputStream是Java用来写入输出的,而InputStream是Java用来读取输入的。从Java的角度来看,外部进程的输出就是输入
因此,您可以使用
getInputStream()
并对其返回的InputStream
调用适当的方法来读取输出。您可能还想使用getErrorStream()
确保不会因为写入标准错误而丢失任何内容。首先,您需要一种非阻塞方式来读取standard.out
和standard.err
private class ProcessResultReader extends Thread
{
final InputStream is;
final String type;
final StringBuilder sb;
ProcessResultReader(@Nonnull final InputStream is, @Nonnull String type)
{
this.is = is;
this.type = type;
this.sb = new StringBuilder();
}
public void run()
{
try
{
final InputStreamReader isr = new InputStreamReader(is);
final BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
{
this.sb.append(line).append("\n");
}
}
catch (final IOException ioe)
{
System.err.println(ioe.getMessage());
throw new RuntimeException(ioe);
}
}
@Override
public String toString()
{
return this.sb.toString();
}
}
然后需要将此类绑定到相应的InputStream
和OutputStream
对象中
try
{
final Process p = Runtime.getRuntime().exec(String.format("cmd /c %s", query));
final ProcessResultReader stderr = new ProcessResultReader(p.getErrorStream(), "STDERR");
final ProcessResultReader stdout = new ProcessResultReader(p.getInputStream(), "STDOUT");
stderr.start();
stdout.start();
final int exitValue = p.waitFor();
if (exitValue == 0)
{
System.out.print(stdout.toString());
}
else
{
System.err.print(stderr.toString());
}
}
catch (final IOException e)
{
throw new RuntimeException(e);
}
catch (final InterruptedException e)
{
throw new RuntimeException(e);
}
当我需要Runtime.exec()
Java中的任何东西时,这几乎就是我使用的锅炉板
更高级的方法是使用FutureTask
和Callable
或至少Runnable
而不是直接扩展线程
,这不是最佳做法
注意:
@Nonnull
注释位于JSR305库中。如果您使用的是Maven,而不是Maven,只需将此依赖项添加到pom.xml
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.9</version>
</dependency>
com.google.code.findbugs
jsr305
1.3.9
这个完整的Java程序示例在命令行上运行命令'dir'(目录列表),将结果拉入字符串并在控制台上打印。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class X {
public static void main(String[] args) {
try{
String command = "dir";
String s = get_commandline_results(command);
System.out.println(s);
}
catch(Exception e){
e.printStackTrace();
}
System.out.println("done");
}
public static String get_commandline_results(String cmd)
throws IOException, InterruptedException, IllegalCommandException{
//Do not remove the authorizedCommand method. Be prepared
//to lose your hard drive if you have not white-listed the
//commands that can run.
if (!authorizedCommand(cmd))
throw new IllegalCommandException();
String result = "";
final Process p = Runtime.getRuntime().
exec(String.format("cmd /c %s", cmd));
final ProcessResultReader stderr = new ProcessResultReader(
p.getErrorStream(), "STDERR");
final ProcessResultReader stdout = new ProcessResultReader(
p.getInputStream(), "STDOUT");
stderr.start();
stdout.start();
final int exitValue = p.waitFor();
if (exitValue == 0){
result = stdout.toString();
}
else{
result = stderr.toString();
}
return result;
}
public static boolean authorizedCommand(String cmd){
//Do not allow any command to be run except for the ones
//that we have pre-approved here. This lessens the
//likelihood that fat fingers will wreck your computer.
if (cmd.equals("dir"))
return true;
//add the commands you want to authorize here.
return false;
}
}
class ProcessResultReader extends Thread{
final InputStream is;
final String type;
final StringBuilder sb;
ProcessResultReader(final InputStream is, String type){
this.is = is;
this.type = type;
this.sb = new StringBuilder();
}
public void run()
{
try{
final InputStreamReader isr = new InputStreamReader(is);
final BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
{
this.sb.append(line).append("\n");
}
}
catch (final IOException ioe)
{
System.err.println(ioe.getMessage());
throw new RuntimeException(ioe);
}
}
@Override
public String toString()
{
return this.sb.toString();
}
}
class IllegalCommandException extends Exception{
private static final long serialVersionUID = 1L;
public IllegalCommandException(){ }
}
在Windows上,这是我得到的结果
Directory of D:\projects\eric\eclipseworkspace\testing2
07/05/2012 01:06 PM <DIR> .
07/05/2012 01:06 PM <DIR> ..
06/05/2012 11:11 AM 301 .classpath
06/05/2012 11:11 AM 384 .project
06/05/2012 11:11 AM <DIR> .settings
07/05/2012 01:42 PM <DIR> bin
06/05/2012 11:11 AM <DIR> src
07/05/2012 01:06 PM 2,285 usernames.txt
3 File(s) 2,970 bytes
5 Dir(s) 45,884,035,072 bytes free
done
D:\projects\eric\eclipseworkspace\testing2目录
2012年5月7日下午1:06。
2012年5月7日下午1:06。。
2012年5月6日上午11:11 301.课堂路径
2012年5月6日上午11:11 384.项目
2012年5月6日上午11:11设置
2012年5月7日下午1:42
2012年5月6日上午11:11 src
2012年5月7日01:06下午2285 usernames.txt
3个文件2970字节
5个目录45884035072字节可用
完成
感谢您的澄清!这有点让人困惑。我现在面临的问题不是打印查询结果(如第二个屏幕截图所示),而是打印查询本身。代码中的内容太多,无法添加到此处的注释中,因此这里有一个指向collabedit文档的链接:我认为,一个问题是
exec()
需要一个实际的可执行文件--批处理文件不是一个可执行程序,它是由Windows shell执行的一系列命令。看,我们真的很接近了!所以现在我的问题是我的缓冲读取器对象为null。我不知道为什么。我已经更新了collabedit文档上的代码。您会注意到我将println放在commandResult的周围,因为这是代码暂停的地方,当commandResult.readLine()应该等于第一个输入行时(或者至少,这是我要查找的)。再次感谢你的帮助!啊,我认为p