0

我想在我的程序中间执行一个批处理文件(这将启动另一个 java 应用程序)。我不想等待或查看它是否成功执行,也不想从执行该批处理文件中捕获错误。在我启动该批处理文件之后,我想做其他事情,而不是在执行该批处理后等待它。

我需要照顾标准输出和标准错误吗?有没有办法摆脱对标准输出和标准错误的处理。

这是我的第二篇文章,以消除我对这个主题的困惑,所以请具体到问题,只是不要抛出有关如何处理.exe 或 processbuilder 的链接。

任何帮助表示赞赏。

4

4 回答 4

3

Short answer: No. As per Process' javadocs,

Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

So you have to take care of the stderr and stdout handling if you want your program to be remotely robust.

Having said that, if you really don't care about their content (which is a bad idea - what if the batch fails with a useful error message that you discard?), you can just fire off threads to read from them, as per Jay R.'s answer. This will let your logic thread continue without worrying about the state of the streams, and the stream eaters will run in the background until the streams are exhausted. You might even want to create a wrapper around Runtime.exec() that fires off threads to do this for you, if you find yourself doing this a lot.

I would, however, at least log the output from the batch process, if you're not going to intepret it in your code. When something goes wrong with the batch, analyzing the problem will be much easier with the process' output to pore over.

于 2010-08-12T16:53:43.747 回答
2

我发现如果你至少不吃 stdout 和 stderr 最终你会耗尽内存。这也阻止了我同时运行多个进程

我一直在使用一个名为 ProcessStreamEater 的类来执行此操作。

public class ProcessStreamEater implements Runnable
{
   private final Process proc;

   public ProcessStreamEater(Process proc)
   {
      this.proc = proc;
   }

   @Override
   public void run()
   {
      InputStreamReader r = new InputStreamReader(proc.getInputStream());
      try
      {
         while(r.read() != -1)
         {  // put stuff here if you want to do something with output
            // otherwise, empty
         }
      }
      catch(IOException e)
      {
         // handle IO exception
      }
      finally
      {
         if(r != null)
         {
            try
            {
               r.close();
            }
            catch(IOException c)
            {}
         }
      }
   }
}

然后当我用它吃东西时...

   ProcessBuilder pb = new ProcessBuilder(args);
   pb.redirectErrorStream(true);
   final Process proc = pb.start();
   executorService.execute(new ProcessStreamEater(proc));

其中 executorService 是使用Executors.newCachedThreadPool ()创建的

于 2010-08-12T16:43:02.577 回答
0

如果您的进程没有对 stdout 或 stderror 产生任何输出,那么您可能不需要处理它。如果您的子进程确实产生了输出,它可能会在尝试写入标准输出时永远阻塞,这取决于操作系统管道缓冲区的大小。这里有一个流冲洗器的例子——每个人都在使用。

于 2010-08-12T16:37:28.407 回答
0

我认为你只需要这个:

Runtime run = Runtime.getRuntime();  
Process p = null;  
String cmd = "D:\\a.bat";     
try {     
  p = run.exec(cmd);
}catch(Exception e){
  //do handling
}

//你的代码

请记住稍后在您的代码中调用 p.destroy()。您也可以在单独的线程中生成上面的代码。希望这可以帮助。

于 2010-08-12T16:18:05.787 回答