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);

但我没有得到任何输出,但当我自己运行该命令时,它工作正常。

336298 次浏览

这里是要走的路:

Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-get t"};
Process proc = rt.exec(commands);


BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));


BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));


// Read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}


// Read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}

阅读Javadoc了解更多详细信息在这里ProcessBuilder将是一个不错的选择。

更快的方法是:

public static String execCmd(String cmd) throws java.io.IOException {
java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}

它基本上是这个的浓缩版本:

public static String execCmd(String cmd) throws java.io.IOException {
Process proc = Runtime.getRuntime().exec(cmd);
java.io.InputStream is = proc.getInputStream();
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
String val = "";
if (s.hasNext()) {
val = s.next();
}
else {
val = "";
}
return val;
}

我知道这个问题是旧的,但我发布这个答案,因为我认为这可能会更快。

编辑(适用于Java 7及更高版本)

需要关闭流和扫描程序。对整洁的代码使用AutoCloseable:

public static String execCmd(String cmd) {
String result = null;
try (InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
Scanner s = new Scanner(inputStream).useDelimiter("\\A")) {
result = s.hasNext() ? s.next() : null;
} catch (IOException e) {
e.printStackTrace();
}
return result;
}

改编自之前的回答:

public static String execCmdSync(String cmd, CmdExecResult callback) throws java.io.IOException, InterruptedException {
RLog.i(TAG, "Running command:", cmd);


Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);


//String[] commands = {"system.exe", "-get t"};


BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));


StringBuffer stdOut = new StringBuffer();
StringBuffer errOut = new StringBuffer();


// Read the output from the command:
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
stdOut.append(s);
}


// Read any errors from the attempted command:
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
errOut.append(s);
}


if (callback == null) {
return stdInput.toString();
}


int exitVal = proc.waitFor();
callback.onComplete(exitVal == 0, exitVal, errOut.toString(), stdOut.toString(), cmd);


return stdInput.toString();
}


public interface CmdExecResult{
void onComplete(boolean success, int exitVal, String error, String output, String originalCmd);
}

尝试读取运行时的InputStream

Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-send", argument};
Process proc = rt.exec(commands);
BufferedReader br = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
String line;
while ((line = br.readLine()) != null)
System.out.println(line);

如果进程正在打印错误输出,则可能还需要读取错误流(proc.getErrorStream())。如果使用ProcessBuilder,则可以将错误流重定向到输入流。

@Senthil和@Arend回答(https://stackoverflow.com/a/5711150/2268559)提到了ProcessBuilder。下面是使用ProcessBuilder并为命令指定环境变量和工作文件夹的示例:

    ProcessBuilder pb = new ProcessBuilder("ls", "-a", "-l");


Map<String, String> env = pb.environment();
// If you want clean environment, call env.clear() first
//env.clear();
env.put("VAR1", "myValue");
env.remove("OTHERVAR");
env.put("VAR2", env.get("VAR1") + "suffix");


File workingFolder = new File("/home/user");
pb.directory(workingFolder);


Process proc = pb.start();


BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));


BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));


// Read the output from the command:
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null)
System.out.println(s);


// Read any errors from the attempted command:
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null)
System.out.println(s);

我们还可以使用流来获取命令输出:

public static void main(String[] args) throws IOException {


Runtime runtime = Runtime.getRuntime();
String[] commands  = {"free", "-h"};
Process process = runtime.exec(commands);


BufferedReader lineReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
lineReader.lines().forEach(System.out::println);


BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
errorReader.lines().forEach(System.out::println);
}

如果用户已经在类路径上提供了Apache Commons-IO,则可以使用:

Process p = new ProcessBuilder("cat", "/etc/something").start();
String stderr = IOUtils.toString(p.getErrorStream(), Charset.defaultCharset());
String stdout = IOUtils.toString(p.getInputStream(), Charset.defaultCharset());

在撰写本文时,包含代码的所有其他答案都可能导致死锁。

进程具有用于stdoutstderr输出的有限缓冲器。如果你不同时听它们,其中一个会在你试着读另一个的时候被填满。例如,您可能正在等待读取stdout,而进程正在等待写入stderr。您无法读取stdout缓冲区,因为它是空的,并且进程无法写入stderr缓冲区,因为它已满。你们永远都在彼此守候。

下面是一种读取进程输出而不发生死锁的可能方法:

public final class Processes
{
private static final String NEWLINE = System.getProperty("line.separator");


/**
* @param command the command to run
* @return the output of the command
* @throws IOException if an I/O error occurs
*/
public static String run(String... command) throws IOException
{
ProcessBuilder pb = new ProcessBuilder(command).redirectErrorStream(true);
Process process = pb.start();
StringBuilder result = new StringBuilder(80);
try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())))
{
while (true)
{
String line = in.readLine();
if (line == null)
break;
result.append(line).append(NEWLINE);
}
}
return result.toString();
}


/**
* Prevent construction.
*/
private Processes()
{
}
}

关键是使用ProcessBuilder.redirectErrorStream(true),它将stderr重定向到stdout流中。这允许您读取单个流,而不必在stdoutstderr之间交替。如果要手动执行此操作,则必须在两个不同的线程中使用流,以确保不会阻止。

与此页面上的其他片段几乎相同,但只是在功能上组织内容,我们开始..

String str=shell_exec("ls -l");

类函数:

public String shell_exec(String cmd)
{
String o=null;
try
{
Process p=Runtime.getRuntime().exec(cmd);
BufferedReader b=new BufferedReader(new InputStreamReader(p.getInputStream()));
String r;
while((r=b.readLine())!=null)o+=r;
}catch(Exception e){o="error";}
return o;
}

如果你在Kotlin上写,你可以使用:

val firstProcess = ProcessBuilder("echo","hello world").start()
val firstError = firstProcess.errorStream.readBytes().decodeToString()
val firstResult = firstProcess.inputStream.readBytes().decodeToString()
Process p = Runtime.getRuntime().exec("ping google.com");


p.getInputStream().transferTo(System.out);


p.getErrorStream().transferTo(System.out);

创建类:

public class Utils {
public static final String SHEL_EXECUTE_ERROR = "SHEL_EXECUTE_ERROR";
public static String shellExec(String cmdCommand) {
final StringBuilder stringBuilder = new StringBuilder();
try {
final Process process = Runtime.getRuntime().exec(cmdCommand);
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}


} catch (Exception e) {
return SHEL_EXECUTE_ERROR;
}
return stringBuilder.toString();
}

}

并使用:

final String shellExec = shellExec("cmd /c ver");
final String versionOS = shellExec.equals(SHEL_EXECUTE_ERROR) ? "empty" : shellExec;