如何将进程输出管道传输到Windows和JDK 6u45上的文件

Bar*_*rak 8 java jdk1.6 processbuilder

我有以下Windows批处理文件(run.bat):

@echo off
echo hello batch file to sysout
Run Code Online (Sandbox Code Playgroud)

以下java代码,它运行批处理文件并将输出重定向到文件:

public static void main(String[] args) throws IOException {
    System.out.println("Current java version is: " + System.getProperty("java.version"));

    ProcessBuilder pb =
            new ProcessBuilder("cmd.exe", "/c",
                    "run.bat"
                     ,">>", "stdout.txt","2>>", "stderr.txt"
                    );
    System.out.println("Command is: " + pb.command());

    Process proc = pb.start();

    InputStream in = proc.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(in));

    String line = null;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

    int exitValue = proc.exitValue();
    System.out.println("Exit value: " + exitValue);
}
Run Code Online (Sandbox Code Playgroud)

在JDK上,包括JDK6u43,我得到以下输出:

Current java version is: 1.6.0_29
Command is: [cmd.exe, /c, run.bat, >>, stdout.txt, 2>>, stderr.txt]
Exit value: 0
Run Code Online (Sandbox Code Playgroud)

并将脚本输出写入文件.从JDK 6u45和7开始,我得到以下输出:

Current java version is: 1.6.0_45
Command is: [cmd.exe, /c, run.bat, >>, stdout.txt, 2>>, stderr.txt]
hello batch file to sysout
Exit value: 0
Run Code Online (Sandbox Code Playgroud)

没有任何内容写入输出文件.

这可能与Runtime.exec()中所做的更改有关,也可能没有,如下所述:http://www.oracle.com/technetwork/java/javase/6u45-relnotes-1932876.html

在输出重定向到文件的Windows上启动进程的正确方法是什么?

注意:在实际场景中,要执行的命令可能包含带空格的参数,如:

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c",
"run.bat", "Some Input With Spaces", 
">>", "stdout.txt","2>>", "stderr.txt");
Run Code Online (Sandbox Code Playgroud)

San*_*ale 10

这是我在http://tamanmohamed.blogspot.in/2012/06/jdk7-processbuilder-and-how-redirecting.html上找到的最简单的方法.

File output = new File("C:/PBExample/ProcessLog.txt");
ProcessBuilder pb = new ProcessBuilder("cmd");
pb.redirectOutput(output);
Run Code Online (Sandbox Code Playgroud)


Dav*_*itz 4

这里有几个建议:

  • 带有空格的输入是否需要被视为单个字符串(带有空格),或者在实际的多个输入中对其进行 id 处理?如果第一个选项是这种情况,我建议在 Windows 运行时引用它:

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", 
"run.bat", "\"Some Input With Spaces\"", 
">>", "stdout.txt","2>>", "stderr.txt");
Run Code Online (Sandbox Code Playgroud)
  • 与其使用 shell 将输入重定向到 stdout.txt 和 stderr.txt,为什么不使用 Java 使用 getOutputStream() 和 getErrorStream() 来实现呢?这是使用 Guava IO 包的示例。当然,您可能希望将它们放在单独的线程中,您需要适当的异常处理等。

InputStream stdout = new BufferedInputStream(proc.getInputStream());
FileOutputStream stdoutFile = new FileOutputStream("stdout.txt");
ByteStreams.copy(stdout, stdoutFile);

InputStream stderr = new BufferedInputStream(proc.getErrorStream());
FileOutputStream stderrFile = new FileOutputStream("stderr.txt");
ByteStreams.copy(stderr, stderrFile);

stdout.close();
stderr.close();
stdoutFile.close();
stderrFile.close();
Run Code Online (Sandbox Code Playgroud)
  • 另一种选择是,为什么不创建一个run.bat进行重定向的包装器呢?

@echo off
cmd.exe /c run.bat "%1" >> "%2" 2>> "%3"
Run Code Online (Sandbox Code Playgroud)