When I saw descriptions about these two methods as below, I felt a bit confused about them.
protected void drain(): Similar to flush but does not propagate the flush to the underlying stream.
void flush(): Writes any buffered output bytes and flush through to the underlying stream.
For example:
FileOutputStream out = new FileOutputStream("test.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);
Question 1:
If I call oout.flush(), it will force the output data in the ObjectOutputStream to be written to the underlying FileOutputStream, but it doesn't guarantee that these data will be subsequently written from FileOutputStream to the file "test.txt" in the disk since I don't call out.flush(), is this correct?
Question 2:
What if I call oout.drain()?
What executions will be done?
Question 1:
If I call oout.flush(), it will force the output data in the ObjectOutputStream to be written to the underlying FileOutputStream, but it doesn't guarantee that these data will be subsequently written from FileOutputStream to the file "test.txt" in the disk since I don't call out.flush(), am I right?
No, you are wrong. It does flush the FileOutputStream. However, as FileOutputStream doesn't buffer or flush, in fact there is no difference between drain() and flush() in this circumstance. If there had been a BufferedOutputStream around the FileOutputStream, there would have been a difference.
Question 2:
What if I call oout.drain()? What executions will be done?
It will flush the ObjectOutputStream but not the underlying stream, exactly as it says in the Javadoc.
You have somehow managed to get this completely back to front. I can't understand how: the Javadoc is quite clear. Also, as drain() is protected it is none of your business anyway.
Flush will write the data to the test.txt. However, drain is similar to flush but does not propagate the flush to the underlying stream.
Related
A third party library casts my SubClassOfOutputStream to a FileOutputStream internally to invoke the getChannel() operation even though they expose an OutputStream interface in their API. This (obviously) causes a ClassCastException.
I need to write to a SubClassOfOutputStream interface. I clearly need to write to a FileOutputStream container, pipe that data to an InputStream, and read bytes from the InputStream in question into my SubClassOfOutputStream instance. Is there a way to do this without disk i/o?
Thanks!
Hi I need a answer for necessity of flush in I/O streams in java.since in my program with flush and without flush the output is same.ie,every thing is written in to the destination file.then why i need flush?will file input stream consumes buffer memory?
the below is my simple sample program
file = new File("c:/newfile.txt");
fop = new FileOutputStream("c:/newfile.txt");
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
// get the content in bytes
byte[] contentInBytes = content.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();
even when i command flush and close it can write the contents in to the file properly..?then y we need flush?and will file outputstream consumes memory?
Close calls flush on the stream, so flush is not needed if you want to close the stream.
Flush is useful if you want to make sure that the data is saved, without closing a stream, e.g. when sending messages over the Internet, or writing to the console. You may notice, that if you write to console with system.out.print(), then the output is not displayed, until you call flush, or until there is a new line in the text (in which case Java will call flush for you).
See more on this question
In fact, FileOutputStream is not buffered, so the data is directly written to the file.
The abstract OutputStream defines flush (an empty method) to accomodate also the needs of buffered streams, so FileOutputStream inherits it.
If you are not certain of the underlying implementation, it is generally good practice to flush the streams before closing them.
Also, in your code there is a little error:
file = new File("c:/newfile.txt");
fop = new FileOutputStream("c:/newfile.txt");
// Will never happen, new FileOutputStream creates the file
if (!file.exists()) {
file.createNewFile();
}
EDIT:
As for the close part of the question:
When you comment out close(), then exiting main() the close method is called by the finalizer (i.e before the stream is garbage collected, a JVM thread calls its finalize() method, which in turn calls the close() method), but you can't sensibly rely on the finalizer: you don't own it and you can't be sure of when it is activated.
Again , best practice is to call close() explicitly.
Explain me please why google coders don't call the flush() method?
/**
* Flushes the stream and forces any buffered bytes to be written. This
* does not flush the underlying OutputStream.
*/
public void flush() throws IOException {
if (output != null) {
refreshBuffer();
}
}
is there any hidden reasons for this?
Because you might not want to flush the underlying stream. For example, you might only want to flush the CodedOutputStream so that you can safely write some other data to the underlying OutputStream and make sure that it ends up being written after the CodedOutputStream's data. In this case you might not want to write the data out to the underlying file or socket yet, because it's more efficient to batch the data.
So of course we must try-catch-finaly any Closable resource.
But I came across some code which sins as follows:
java.util.Properties myProps = ... reads & loads (and doesn't close Stream!)
myProperties.store(new FileOutputStream(myFilePath), null);
System.exit(0);
java.util.Properties.store() flushes the underlying stream (the FileOutputStream)
Will this be enough?
Can you think of a scenario where the file won't be written? assuming that the method passes and no exception is being thrown in 'store'
It is enough in this specific case, but it is nevertheless very bad practice. The FileOutputStream should be closed, not merely flushed.
If you don't want open file references I would close the streams. Flushing only makes sure that all changes are written to file.
I am streaming binary data (a CSV file extracted from the database as a Clob) to the browser by calling response.getOutputStream() and would normally wrap the OutputStream in a BufferedOutputStream when copying the data.
Should I close the BufferedOutputStream or will this also close the underlying OutputStream?
[Extra question: Do I need to use a BufferedOutputStream in this case or is the response already buffered?]
Yes, it closes it. As for whether you should close it - are you expecting to write anything else to the response stream? If not, I think it's fine to close it. If you don't close it, you should obviously flush it instead - but I suspect you could figure that bit out for yourself :)
The behaviour is actually inherited from FilterOutputStream. The Javadocs for for FilterOutputStream.close state:
The close method of FilterOutputStream
calls its flush method, and then calls
the close method of its underlying
output stream.
As for whether you should buffer it - I'm not sure that this is well defined. It may be buried in the servlet spec somewhere - and it may even be configurable (sometimes you really don't want buffering, but if you can buffer the whole response it means you can serve a nicer error page if things go wrong after you've started writing).
Closing the BufferedOutputStream will also close the underlying OutputStream. You should close the BufferedOutputStream so that it flushes its contents before closing the underlying stream. See the implementation of FilterOutputStream.close() (from which BufferedOutputStream extends) to convince yourself.
I guess that whether or not the response stream given to your servlet is buffered or not depends on the implementation of your Servlet Container. FWIW I know that Tomcat does buffer its servlet response streams by default, in order to attempt to set the content-length HTTP header.