【问题标题】:IOUtils.copy() hangs when copying big stream?复制大流时 IOUtils.copy() 挂起?
【发布时间】:2014-07-30 14:03:52
【问题描述】:

我想通过srcML 解析器解析某些文件的内容,它是一个外部windows 程序。我正在通过以下方式执行此操作:

String command = "src2srcml.exe --language java";
Process proc = Runtime.getRuntime().exec(command);

InputStream fileInput = Files.newInputStream(file)
OutputStream procOutput = proc.getOutputStream();

IOUtils.copy(fileInput, procOutput);

IOUtils.copy() 来自 Commons IO 2.4 库。

当我的文件很小(几 KB)时,一切正常。但是,当我尝试复制一些相对较大的文件(~72 KB)时,我的程序挂起。

此外,当我在 cmd 中“手动”执行解析器时:

src2srcml.exe --language Java < BigFile.java

一切正常,也是。

任何想法为什么会发生这种情况?

【问题讨论】:

  • 您确定问题出在大小而不是流本身吗?有一种方法 IOUtils.copyLarge(in, out),但适用于大于 2GB 的流。所以 72 KB 应该不是问题。
  • @luanjot 你可能是对的。但是,这可能是什么问题?字符编码?
  • 我无法帮助你,因为我不知道 src2srcml 是如何工作的。输出是什么?文本?你能以任何方式将它打印到控制台吗?
  • 外部程序是否在标准输出上生成输出?
  • @jtahlborn 是的,确实如此

标签: java stream apache-commons-io


【解决方案1】:

你应该缓冲 OutputStream:

OutputStream procOutput = proc.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(procOutput);
IOUtils.copy(fileInput, bos);

另外,为什么不直接将fileInput重定向为进程InputStream呢?

 ProcessBuilder pb = new ProcessBuilder(command);
 pb.redirectInput(file);
 Process proc = pb.start();
 proc.waitFor();

【讨论】:

  • 谢谢,使用 BufferedOutputStream 有效。我不能简单地重定向输入,因为事实上我的输入流是一个 ReplaceInputStream(我需要在解析之前替换几个字符)。
  • @Kao - 使用 BufferedOutputStream 只是部分解决方案。当您的输入足够大时,它将再次失败。看我的回答。
  • @jtahlborn 但是 Java 程序正在管道到外部程序,所以这不应该需要 Java 程序中的另一个线程。 (反过来:绝对!)
  • @laune 我想使用您在答案第二部分中提到的 ProcessBuilder。但是,有没有办法将输入重定向到 Stream? pb.redirectInput() 只接受 File 或 ProcessBuilder.Redirect,只能从 File 中创建。
  • @Kao 在这种情况下,使用 Process.getOutputStream(),包装成一个 BuffredOutputStream 并写入它。
【解决方案2】:

问题很可能是您没有在单独的线程中使用外部程序的输出。您需要启动一个单独的线程来消耗输出,以免外部程序被阻塞。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 2010-12-14
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多