posted 21 years ago
1. Without the line bos.flush();, my image was still getting corrupted. Why is it so?
Hmmm, hard to say for sure. Usuallyeach close() normally does a flush() too, so you normally don't need to insert this yourself unless you want to ensure the bytes are flushed in cases where the stream has not yet been closed. E.g. if you want to see intermediate results while a file is still printing, or if you want to ensure output is flushed even when to program is terminated prematurely. (Thing like System.exit() and ctrl-C may not allow the JVM to flush streams before exiting.) However, the API for OutputStream doesn't actually guarantee that a flush is done() as part of a close(). It's performed bya FilterOutputStream, as well as by any Writer. But it's not guaranteed for OutputStreams in general. So I guess we really should get in the habit of flushing an OutputStream before closeing it.
Is it possible that an error was thrown somewhere in the finally statement, before the bos.close()? I often favor putting different stream closures in separate try-catch blocks, even separate methods, to be safe. E.g.
This can be called from your fetchContent method, which now doesn't have to worry about the output streams at all. It's easy to see that the stream is flushed and closed int the same method that opens it, with no chance of any unrelated exceptions preventing the close from being called. (If an IOException occurs I don't care so much about flushing, but I care that the file is not held open, because sometimes the subequent code is going to delete or move the file, and open file streams interfere with this.) Note that the way this is structured, there's no need to check if out == null. If the constructor complete successfully, out is not null, and the close() will be called. If an exception is thrown during contruction, out will not have been constructed, and it's neither necessary nor possible to close it.
You can add as much complex error handling as you need to here. In many cases I might want to throw or re-throw an exception to indicate the file write did not occur. Here I just caught and logged the problem. You've got many possible options. The point here is to deal with the output steam in one method, separate from error handling for the input stream. Error handling gets messy and unreadable if you're dealing with too many things at once, and the chance of mistakes increases dramatically.
2. What would be the difference in efficiency between using Buffered streams and using manual byte buffer
They're pretty close really. I tend to use manual buffering; it's a bit faster in most cases. If I'm moving a lot of data and a bulk read or write is available, I use it. I think of that as a standard paradigm that everyone who uses Java IO should learn. Most of the time it doesn't really matter much - the main benefit is in having some sort of buffer, somewhere. I suppose I could have omitted my "more efficient" example since you were already using buffered streams. But manual buffering is beneficial often enough that I think programmers should know how to use it.
"I'm not back." - Bill Harding, Twister