Java 过程赢得';除非打印输出+;Processbuilder

Java 过程赢得';除非打印输出+;Processbuilder,java,Java,我遇到了一个奇怪的问题。我曾多次使用process builder从程序中调用可执行文件,但以前从未遇到过这种情况。出于调试目的,我制作了一个方法,将可执行文件的输出打印到System.out。一切正常,我的程序很好地导出了我运行的所有测试GIF 当需要为1000+个GIF正确运行此程序时,我注释了打印输出方法以提高性能。整个程序运行后,我回来发现exportGif无法工作。程序运行时没有出现任何错误,但进程的调用没有按预期导出GIF 在printout方法中隔离行之后,代码的决定位似乎是rea

我遇到了一个奇怪的问题。我曾多次使用process builder从程序中调用可执行文件,但以前从未遇到过这种情况。出于调试目的,我制作了一个方法,将可执行文件的输出打印到System.out。一切正常,我的程序很好地导出了我运行的所有测试GIF

当需要为1000+个GIF正确运行此程序时,我注释了打印输出方法以提高性能。整个程序运行后,我回来发现exportGif无法工作。程序运行时没有出现任何错误,但进程的调用没有按预期导出GIF

在printout方法中隔离行之后,代码的决定位似乎是
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);
    }
private void printProcessOutput(进程){
缓冲读取器=
新的BufferedReader(新的InputStreamReader(process.getInputStream());
StringBuilder=新的StringBuilder();
字符串行=null;
试一试{
而((line=reader.readLine())!=null){
builder.append(行);
append(System.getProperty(“line.separator”);
}
}捕获(IOE异常){
e、 printStackTrace();
}
System.out.println(builder.toString());
}
私有void exportGIF(字符串dirPath)引发IOException{
列表行=Arrays.asList(“/Users/IdeaProjects/MasterFormat/MasterFormat Java/MasterFormat/timMaster_4.1.png\”{200.0467.0}\”);
Path headImageFile=Path.get(System.getProperty(“user.dir”)+File.separator+“headImageInfo.txt”);
write(headImageFile,line,Charset.forName(“UTF-8”);
字符串templatePath=dirPath+File.separator+“template.mp4”;
字符串outputPath=dirPath+File.separator;
字符串headImagePath=headImageFile.toString();
字符串gifExportExecPath=“/Users/IdeaProjects/MasterFormat/MasterFormat Java/MasterFormat/GIFExport”;
Process Process=new ProcessBuilder(gifExportExecPath、“-s”、templatePath、“-o”、outputPath、“-h”、headImagePath).start();
printProcessOutput(过程);
文件。删除(headImageFile);
}
编辑

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


当我包含打印输出方法时,速度要慢得多。我试着在一夜之间运行它,但经过183次迭代后它就卡住了。我试图分析它是否引起了一些震动,但GC似乎运行良好

您需要消耗进程的输出,否则它可能会挂起。所以你不能注释掉
printProcessOutput(进程)。相反,请注释掉实际进行打印的行:

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

你写“程序运行时没有错误”,这意味着它没有“挂起”,对吗?因此,我认为这与这里的情况不同:从Javadoc for Process:“默认情况下,创建的子流程没有自己的终端或控制台。其所有标准I/O(即stdin、stdout、stderr)操作都将重定向到父进程,[…]由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此未能及时写入子流程的输入流或读取子流程的输出流可能会导致子流程阻塞,甚至死锁。”,该过程实际上正在等待完成,您可能会发现内存泄漏没有占用err/out流。