Процесс выполнения Java waitfor не кажется ожидающим - PullRequest
0 голосов
/ 21 февраля 2012

Мне нужно написать программу, которая требуется для запуска нескольких других программ через вызовы командной строки. Программа 1 создает файл, который программа 2 затем читает. Я следовал различным примерам того, как сделать это безопасно, но все еще имею одну досадную проблему. Код ниже в основном работает, но только если присутствует system.out после waitfor(). Если я уберу это, я получу ошибку (см. Ниже). Мне немного неудобно с кодом, если я не знаю, почему что-то происходит.

Любая помощь приветствуется.

Код:

public static int executeCommandWithOutputfile(String command,
      String outputFile) {
   int exitVal = 0;

   try {
      FileOutputStream fos = new FileOutputStream(outputFile);
      Runtime rt = Runtime.getRuntime();
      Process proc = rt.exec(command);

      // any error message?
      StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(),
            "ERROR");

      // any output?
      StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(),
            "OUTPUT", fos);

      // kick them off
      errorGobbler.start();
      outputGobbler.start();

      // any error???
      exitVal = proc.waitFor();
      //don't remove this system out, when I did I got errors.
      //System.out.println("ExitValue: " + exitVal);
      fos.flush();
      fos.close();
   } catch (Throwable t) {
      t.printStackTrace();
   }
   return exitVal;
}

Выход с целой строкой System.out:

    ExitValue: 0
    ExitValue: 0
    ExitValue: 0
    Release note complete.

Выход с удаленным system.out:

    [Fatal Error] tmpRelNote2482381115742032425xml:1:1: Premature end of file.
    Error : The XML config file is not valid!
    Exception in thread "main" java.lang.NullPointerException
        at rwe.release.CreateReleaseNote.insertReleaseInfo(CreateReleaseNote.java:96)
        at rwe.release.CreateReleaseNote.writeReleaseNote(CreateReleaseNote.java:81)
        at rwe.release.CreateReleaseNote.<init>(CreateReleaseNote.java:30)
        at rwe.release.CreateReleaseNote.main(CreateReleaseNote.java:19)
    Process exited with exit code 1.

Ответы [ 2 ]

2 голосов
/ 21 февраля 2012

Ваш код имеет состояние гонки. OutputGobbler может закончиться или не закончиться, поглотив выходные данные процесса при вызове fos.close(). println замедляет этот поток настолько, чтобы дать гоблеру время завершить обработку выходных данных процесса.

Вы должны убедиться, что OutputGobbler передал все выходные данные в файл, прежде чем закрыть файл.

0 голосов
/ 21 февраля 2012

Вы уверены, что проблема связана с waitFor ()?

Я думаю, что проблема заключается в очистке OutputStream внешней команды, которая объясняет, почему System.out.println () решает проблему. Попробуйте сделать явный System.out.flush () после возврата waitFor ().

Из процесса javadoc: "Созданный подпроцесс не имеет собственного терминала или консоли. Все его стандартные операции io (т.е. stdin, stdout, stderr) будут перенаправлены в родительский процесс через три потока (getOutputStream (), getInputStream ( ), getErrorStream ()). "

...