【问题标题】:Java prog piped and returned immediatelyJava prog 通过管道传输并立即返回
【发布时间】:2014-12-21 14:31:46
【问题描述】:

我有一个打印到标准输出的 Java 程序。如果输出通过管道传送到,比如head,shell 不会在 head 完成其工作后立即返回,而是等待 Java 程序完成所有工作。

所以我的问题是:如何编写 Java 程序以便 shell 立即返回,就像 cat ... | head 一样?

这是我的意思的一个例子:

这里 shell 立即返回,因为 head 不会花时间打印前十行,无论 bigfile.txt 有多大:

time cat bigfile.txt | head
...
real    0m0.079s
user    0m0.001s
sys     0m0.006s

在这里,前十行被快速打印,但在处理完所有文件之前,shell 不会返回:

time java -jar DummyReader.jar bigfile.txt | head
...
real    0m18.720s
user    0m16.936s
sys     0m2.212s

DummyReader.jar 尽可能简单:

import java.io.*;

public class DummyReader {

    public static void main(String[] args) throws IOException {

        BufferedReader br= new BufferedReader(new FileReader(new File(args[0])));   
        String line;
        while((line= br.readLine()) != null){
            System.out.println(line);
        }
        br.close();
        System.exit(0);
    }

}

我的设置:

java -version
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-10M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

在 MacOS 10.6.8 上

【问题讨论】:

  • 那么,您基本上希望head 在打印前 10 行之后杀死您的 Java 程序?
  • @tobias_k 是的,没错,我想去头(或下游的任何东西)杀死java程序。
  • 我不确定head 的工作原理。也许您宁愿编写自己的“杀头”功能。或者将参数传递给您的 Java 脚本,告诉它在 x 行后停止。
  • @tobias_k 正如我所说,前十行由 head (几乎)立即打印,这很好。但是,在处理完所有文件之前,shell 不会返回,这在我的示例中意味着等待约 18 秒。
  • 在 POSIX 系统(Unix、Linux 等)上,操作系统通过在 head 关闭管道一侧后尝试写入更多数据时向 cat 发送 SIGPIPE 信号来处理此问题。我不确定你的 Java 程序为什么没有捕捉到这个信号并中止。

标签: java shell pipe


【解决方案1】:

这只是因为您没有在 println 调用之后检查错误。这是一个确实停止的修订版本。不过,它会更慢,因为 checkError() 会刷新到目前为止已缓冲的所有输出。

可能还有其他方法可以在不减慢速度的情况下获得有关错误的通知。我见过一些明确处理 SIGPIPE 信号的代码,但我不知道这是否是最好的方法。

import java.io.*;

public class DummyReader {

    public static void main(String[] args) throws IOException {

        BufferedReader br= new BufferedReader(new FileReader(new File(args[0])));   
        String line;
        int linecount = 0;
        while((line= br.readLine()) != null){
            System.out.println(line);
            if (System.out.checkError())
            {
                System.err.println("Got some sort of error in the output stream");
                break;
            }
            linecount++;
        }
        br.close();
        System.err.println("Read " + linecount + " lines.");
        System.exit(0);
    }

}

【讨论】:

  • 谢谢!这正是我所要求的。我会看看你提到的减速有多糟糕......
猜你喜欢
  • 2021-07-29
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多