Вопрос по stdin, stdout, java, exec – Запуск внешней программы с перенаправленным stdin и stdout из Java

4

Я пытаюсь запустить внешнюю программу из Java-программы, и у меня возникли проблемы. По сути, я хотел бы сделать следующее:

 Runtime.getRuntime().exec("./extprogram <fileIn >fileOut");

Однако я обнаружил, что это не работает - очевидно, Java должен использоватьProcess с входными и выходными потоками и другими вещами, с которыми я не сталкивался.

Я рассмотрел несколько примеров в Интернете (многие из которых получены от SO), и, похоже, не существует простого стандартного способа сделать это, что для человека, который не полностью понимает, что происходит. на, может быть довольно сложно.

У меня также возникают проблемы при попытке создать собственный код из примеров кода других людей, потому что, как правило, большинство других людей 1. не заинтересованы в перенаправленииstdinи 2. не обязательно перенаправляютstdout в файл, но вместоSystem.out.

Итак, кто-нибудь сможет указать мне в направлении каких-либо хороших простых шаблонов кода для вызова внешних программ и перенаправленияstdin а такжеstdout? Благодарю.

Ваш Ответ

3   ответа
8

Вы можете попробовать что-то вроде этого:

ProcessBuilder pb = new ProcessBuilder();
pb.redirectInput(new FileInputStream(new File(infile));
pb.redirectOutput(new FileOutputStream(new File(outfile));
pb.command(cmd);
pb.start().waitFor();
Это прискорбно. Это было в течение почти года, и довольно проверено в бою. :-( Надеюсь, что «старая школа» представится!
1+, но не забывайте поток ошибок, который можно сложить в InputStream процесса, вызвавbp.redirectErrorStream(true).
ProcessBuilder не имеетredirectInput() илиredirectOutput() функция.docs.oracle.com/javase/1.5.0/docs/api/java/lang/… MattS
Ах, я только на Java 6. К сожалению, на данный момент обновление не вариант. MattS
@MattS \ s \ 1.5.0 \ 7docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
0

Вы пробовали System.setIn и System.setOut? был вокруг с JDK 1.0.

public class MyClass
{
    System.setIn( new FileInputStream( "fileIn.txt" ) );
    int oneByte = (char) System.in.read();
    ...

    System.setOut( new FileOutputStream( "fileOut.txt" ) );
    ...
6

Если вы должны использоватьProcessто как то так должно работать:

public static void pipeStream(InputStream input, OutputStream output)
   throws IOException
{
   byte buffer[] = new byte[1024];
   int numRead = 0;

   do
   {
      numRead = input.read(buffer);
      output.write(buffer, 0, numRead);
   } while (input.available() > 0);

   output.flush();
}

public static void main(String[] argv)
{
   FileInputStream fileIn = null;
   FileOutputStream fileOut = null;

   OutputStream procIn = null;
   InputStream procOut = null;

   try
   {
      fileIn = new FileInputStream("test.txt");
      fileOut = new FileOutputStream("testOut.txt");

      Process process = Runtime.getRuntime().exec ("/bin/cat");
      procIn = process.getOutputStream();
      procOut = process.getInputStream();

      pipeStream(fileIn, procIn);
      pipeStream(procOut, fileOut);
   }
   catch (IOException ioe)
   {
      System.out.println(ioe);
   }
}

Замечания:

  • Be sure to close the streams
  • Change this to use buffered streams, I think the raw Input/OutputStreams implementation may copy a byte at a time.
  • The handling of the process will probably change depending on your specific process: cat is the simplest example with piped I/O.
MattS: я немного обновил код, более ранняя обработка потока имела несколько проблем (я не думал о достаточной обработке потока). Эти изменения могут помочь. Также добавлено несколько заметок.
Это работает для меня! Огромное спасибо. Есть только одна последняя проблема, с которой я столкнулся с этим кодом - когда программа завершена, файлы пусты (у них уже были данные - она использовалась программой). С чего бы это? MattS
@ pb1q Отлично, я немного расскажу об этом. С таким же кодом, как и раньше, я не забывал закрывать потоки ввода / вывода, но забыл закрыть поток ошибок процесса, который вызывал сбой из-за слишком большого количества открытых файлов одновременно. Еще раз спасибо. MattS

Похожие вопросы