Reputation: 9062
I have a Java program that prints to stdout. If the output is piped to, say, head
the shell doesn't return immediately after head has done its job, instead it waits for the Java program to complete all its work.
So my question is: How can I write the Java program so that the shell returns immediately, just like cat ... | head
?
This is an example for what I mean:
Here the shell returns immediately as head
takes no time to print the first ten line, no matter how big bigfile.txt
is:
time cat bigfile.txt | head
...
real 0m0.079s
user 0m0.001s
sys 0m0.006s
Here instead the first ten lines are quickly printed but the shell doesn't return until all the file is processed:
time java -jar DummyReader.jar bigfile.txt | head
...
real 0m18.720s
user 0m16.936s
sys 0m2.212s
DummyReader.jar
is as simple as I could make it:
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);
}
}
My settings:
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)
On MacOS 10.6.8
Upvotes: 4
Views: 67
Reputation: 464
It's just because you're not checking for errors after the println call. Here's a revised version that does stop. It will be slower, though, because checkError() flushes any output that has been buffered so far.
There may be other ways to get notified about the error without the slowdown. I've seen some code that explicitly handles the SIGPIPE signal, but I don't know if that's the best way to do it.
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);
}
}
Upvotes: 2