Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You know, I kind of thought he was joking that Java programmers messed this stuff up.

I was so wrong.

Three things wrong. The first is pedantic: you need to import IOException. The second though is one of those "scream out loud at the universe* questions: why the heck are you calling print() instead of write()?

Finally, do you think maybe you might need to worry about buffering of System.out's stream?



> Finally, do you think maybe you might need to worry about buffering of System.out's stream?

print() won't flush to the console unless you pass '\n' and auto-flushing is on. It will flush its internal buffer, but that's okay! The default System.out uses a BufferedOutputStream anyway:

    FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
    ...
    new PrintStream(new BufferedOutputStream(fdOut, 128), true)
So using print() instead of write() shouldn't cause any extra system calls, although there many be a small CPU cost.

Obvious, right? Don't you love java.io? :)


> The default System.out uses a BufferedOutputStream anyway

Yes, which is the _problem_, not the _solution_.

To clarify: the problem isn't that the code makes too many syscalls.


So what are you saying is the problem then? That writing to the BufferedOutputStream for each character is CPU-inefficient and he should be doing this?

    public static void main(String[] args) throws IOException {
        byte[] buffer = new byte[1 << 12];
        for (;;) {
            int nRead = System.in.read(buffer);
            if (nRead == -1) return;
            System.out.write(buffer, 0, nRead);
        }
    }
If so, fair enough, but it's reasonable to go with the simpler solution if you're not given any particular performance requirements.


No, I'm saying you are already using a BufferedInputStream and a BufferedOutputStream. That is the problem: you aren't guaranteeing your output matches your input.

Try doing this:

    dd if=/dev/random of=test_file bs=4000 count=100
    java YourClass < test_file > test_output
    diff test_file test_output


Here's the simpler, likely slower, but nonetheless actually correct solution: https://gist.github.com/cbsmith/9755809


Oh, gotcha. The code above with "byte[] buffer" also works since write(byte[], int, int) flushes.


I mean, if you really want to be pedantic...

> you need to import IOException

    try {
        ...
    } catch(Exception ex){ ... }
;-)

Edit: Or if you want to be just as pedantic, and not write an obnoxious catch-all

    try { 
        ... 
    } catch (java.io.IOException ex) { ... }


I'm not sure why you'd want to use a catch, but I agree there is more than one way to solve the problem. I was merely pointing out one thing that would prevent the code from passing the test framework.


Sorry, I didn't think I was telling you something which you didn't already know. I just saw a hole in the pedantry and felt a strange need to point it out. Now that I've typed that, I realize what a horrible person I am.

As to why you'd want to use a catch, I think it's kind of sloppy to let the user see an uncaught exception. You might as well just do

    public static void main(String args[]){ 
        try {
            ...
        } catch (Exception e) {
            System.out.println("This is horrible software, and you shouldn't use it.");
        }
    }
... as that's what many users already see when exception goes uncaught.


I could see a try/catch with a System.exit(-1) maybe, but arguably the default handler does the right thing (returns an error code and writes diagnostics to stderr).


He wrote the code to show you that you don't need to import IOException you can use a catch all to avoid a throws statement in the method header.

This is bad code as he said.


> He wrote the code to show you that you don't need to import IOException you can use a catch all to avoid a throws statement in the method header.

You're conflating two things. I could just as easily have caught Throwable or Exception and not needed the import. The question is: what would you actually put in the handler that would be so much better? The actually provided sample code is much worse, as it prints to System.out instead of System.err, and it doesn't report an error to the parent process, so you muddy up the output (imagine if the file you were copying actually ended in "This is horrible software, and you shouldn't use it.", how would you even know) and there is not a terribly easy way to detect an error happened.

> This is bad code as he said.

It's not bad code to declare a static exception as escaping your method, particularly if you don't have any logic for handling it. It's bad code to have an exception handler that doesn't.


Isn't there a Steam.copyTo(Stream) method somewhere? Or was that .NET?


Yes, Apache Commons has IOUtils.copy and Guava has a similar ByteStreams.copy.


Looks like I don't get the job.


Here's the thing though... Those mistakes you made aren't language specific. What languages don't expose you to making similar mistakes?

There are some, but they aren't the ones people usually think of when they say, "I'd always use X instead of Java".


It mostly is language specific though isn't it? Take python: IOError is a global, one main way to print, you don't have to worry about the output buffer.


Oh no. Python has lots of ways to print. You can actually pretty easily hose that part up in Python, and Python doesn't require the flush because it automatically closes/flushes the stream. In general (as in, if you didn't know you were using sys.in and sys.out) in Python you'd want to use a "with" statement to ensure that really happens.

So, for example, if you are in Python3, sys.in and sys.out are by default in text mode, which is not going to end well for anyone.


Well, if I were making the test framework for this test, I'd only send ASCII text to the programs.

It's a trivial test, so I'll give you trivial input and not have you worry about "what if someone gives me random bytes".

The test isn't to demonstrate you know off the top of your head how to deal with an edge case. But if it were and I were allowed to pick my language, I'd pick bash and just write

  cat


> The test isn't to demonstrate you know off the top of your head how to deal with an edge case.

The only edge case is knowing you need to flush the output, which is relevant whether you send ASCII text or not. The other edge cases around ASCII are just whether you use the correct API's or not.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: