除非打印输出+ Processbuilder,否则进程不会运行

时间:2017-05-05 15:47:27

标签: java

我遇到了一个奇怪的问题。我已经多次使用进程构建器从程序中调用可执行文件,但之前从未遇到过。出于调试目的,我创建了一个方法,将可执行文件的输出打印到System.out。一切正常,我的程序很好地导出了我运行的所有测试GIF。

当需要为1000多个GIF正确运行此程序时,我注释掉了打印输出方法以提高性能。一旦整个程序运行,我回来发现exportGif不起作用。该程序运行没有错误,但调用该进程根本没有按预期导出gif。

在打印输出方法中隔离行之后,似乎代码的决定位是reader.readLine()。为什么会这样呢?可执行文件应该已经运行了,调试方法应该只在事后读取输出流,对吗?我不想每次循环它的输出流,因为它会导致程序显着减慢。

    private void printProcessOutput(Process process){
        BufferedReader reader =
                new BufferedReader(new InputStreamReader(process.getInputStream()));
       StringBuilder builder = new StringBuilder();
       String line = null;

        try{
            while ( (line = reader.readLine()) != null) {
                builder.append(line);
                builder.append(System.getProperty("line.separator"));
            }
        }catch(IOException e){
            e.printStackTrace();
        }

        System.out.println(builder.toString());
    }

    private void exportGIF(String dirPath) throws IOException {
        List<String> lines = Arrays.asList("/Users/IdeaProjects/MasterFormat/MasterFormat-Java/MasterFormat/timMaster_4.1.png \"{200.0,467.0}\"");
        Path headImageFile = Paths.get(System.getProperty("user.dir") + File.separator +  "headImageInfo.txt");
        Files.write(headImageFile, lines, Charset.forName("UTF-8"));

        String templatePath = dirPath + File.separator + "template.mp4";
        String outputPath = dirPath + File.separator;
        String headImagePath = headImageFile.toString();
        String gifExportExecPath = "/Users/IdeaProjects/MasterFormat/MasterFormat-Java/MasterFormat/GIFExport";

        Process process = new ProcessBuilder(gifExportExecPath, "-s", templatePath, "-o", outputPath, "-h", headImagePath).start();

        printProcessOutput(process);

        Files.delete(headImageFile);
    }

修改

我应该补充一点。我注意到当我注释掉调试方法时,它会在不到十分钟的时间内完成所有1000多次迭代,但是,当然gifs不会导出(可执行文件没有运行......?不确定)。

当我包含打印输出方法时,它要慢得多。我试着在一夜之间运行它但在183次迭代后它被卡住了。我试过分析,看它是否引起了一些颠簸,但GC似乎运行正常。

1 个答案:

答案 0 :(得分:2)

您需要使用Process的输出,否则它可能会挂起。所以你不能评论printProcessOutput(process);。相反,注释掉实际打印的行:

try{
  while ( (line = reader.readLine()) != null) {
    //builder.append(line);
    //builder.append(System.getProperty("line.separator"));
  }
} catch(IOException e){
    e.printStackTrace();
}
//System.out.println(builder.toString());

我通常使用这种方法,它也重定向错误流:

public static void runProcess(ProcessBuilder pb) throws IOException {
  pb.redirectErrorStream(true);
  Process p = pb.start();
  BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
  String line;
  while ((line = reader.readLine()) != null) {
    //System.out.println(line);
  }
}