9

次の Windows バッチ ファイル (run.bat) があります。

@echo off
echo hello batch file to sysout

次の 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);
}

JDK6u43 までの JDK では、次の出力が得られます。

Current java version is: 1.6.0_29
Command is: [cmd.exe, /c, run.bat, >>, stdout.txt, 2>>, stderr.txt]
Exit value: 0

スクリプト出力がファイルに書き込まれます。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

出力ファイルには何も書き込まれません。

これは、 http://www.oracle.com/technetwork/java/javase/6u45-relnotes-1932876.htmlで説明されている Runtime.exec() で行われた変更に関連している場合と関連していない場合があります。

出力をファイルにリダイレクトして Windows でプロセスを開始する正しい方法は何ですか?

注: 実際のシナリオでは、実行するコマンドには、次のようにスペースを含むパラメーターが含まれる場合があります。

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

3 に答える 3

17

これは、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);
于 2013-09-05T07:35:37.573 に答える
4

ここにいくつかの提案があります:

  • スペースを含む入力は、単一の文字列 (スペースを含む) として扱う必要がありますか、それとも実際の複数の入力でそれを識別しますか? 最初のオプションが当てはまる場合は、Windows ランタイムに引用することをお勧めします。

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", 
"run.bat", "\"Some Input With Spaces\"", 
">>", "stdout.txt","2>>", "stderr.txt");
  • シェルを使用して入力を 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.bat、リダイレクトを行うラッパーを作成してみませんか?

@echo off
cmd.exe /c run.bat "%1" >> "%2" 2>> "%3"
于 2013-06-13T19:58:19.930 に答える
0

を使用するgetOutputStream()代わりに、プロセスで使用しSystem.out.println()ます。Java 実装間でセマンティクスが変わることがあります。

これは実際にはバグ修正のようです - 新しい実装は理にかなっています。

于 2013-06-13T15:06:03.023 に答える