The Java 7 try-with-resources syntax (also known as ARM block (Automatic Resource Management)) is nice, short and straightforward when using only one AutoCloseable resource. However, I am not sure what is the correct idiom when I need to declare multiple resources that are dependent on each other, for example a FileWriter and a BufferedWriter that wraps it. Of course, this question concerns any case when some AutoCloseable resources are wrapped, not only these two specific classes.
I came up with the three following alternatives:
1)
The naive idiom I have seen is to declare only the top-level wrapper in the ARM-managed variable:
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
This is nice and short, but it is broken. Because the underlying FileWriter is not declared in a variable, it will never be closed directly in the generated finally block. It will be closed only through the close method of the wrapping BufferedWriter. The problem is, that if an exception is thrown from the bw's constructor, its close will not be called and therefore the underlying FileWriter will not be closed.
2)
static void printToFile2(String text, File file) {
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
Here, both the underlying and the wrapping resource are declared in the ARM-managed variables, so both of them will certainly be closed, but the underlying fw.close() will be called twice: not only directly, but also through the wrapping bw.close().
This should not be a problem for these two specific classes that both implement Closeable (which is a subtype of AutoCloseable), whose contract states that multiple calls to close are permitted:
Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.
However, in a general case, I can have resources that implement only AutoCloseable (and not Closeable), which doesn't guarantee that close can be called multiple times:
Note that unlike the close method of java.io.Closeable, this close method is not required to be idempotent. In other words, calling this close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once. However, implementers of this interface are strongly encouraged to make their close methods idempotent.
3)
static void printToFile3(String text, File file) {
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
This version should be theoretically correct, because only the fw represents a real resource that needs to be cleaned up. The bw doesn't itself hold any resource, it only delegates to the fw, so it should be sufficient to only close the underlying fw.
On the other hand, the syntax is a bit irregular and also, Eclipse issues a warning, which I believe is a false alarm, but it is still a warning that one has to deal with:
Resource leak: 'bw' is never closed
So, which approach to go for? Or have I missed some other idiom that is the correct one?
Here's my take on the alternatives:
1)
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
}
For me, the best thing coming to Java from traditional C++ 15 years ago was that you could trust your program. Even if things are in the muck and going wrong, which they often do, I want the rest of the code to be on best behaviour and smelling of roses. Indeed, the BufferedWriter might throw an exception here. Running out of memory wouldn't be unusual, for instance. For other decorators, do you know which of the java.io wrapper classes throw a checked exception from their constructors? I don't. Doesn't do code understandability much good if you rely upon that sort of obscure knowledge.
Also there's the "destruction". If there is an error condition, then you probably don't want to be flushing rubbish to a file that needs deleting (code for that not shown). Although, of course, deleting the file is also another interesting operation to do as error handling.
Generally you want finally blocks to be as short and reliable as possible. Adding flushes does not help this goal. For many releases some of the buffering classes in the JDK had a bug where an exception from flush within close caused close on the decorated object not be called. Whilst that has been fixed for some time, expect it from other implementations.
2)
try (
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)
) {
bw.write(text);
}
We're still flushing in the implicit finally block (now with repeated close - this gets worse as you add more decorators), but the construction is safe and we have to implicit finally blocks so even a failed flush doesn't prevent resource release.
3)
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
}
There's a bug here. Should be:
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
bw.flush();
}
Some poorly implemented decorators are in fact resource and will need to be closed reliably. Also some streams may need to be closed in a particular way (perhaps they are doing compression and need to write bits to finish off, and can't just flush everything.
Verdict
Although 3 is a technically superior solution, software development reasons make 2 the better choice. However, try-with-resource is still an inadequate fix and you should stick with the Execute Around idiom, which should have a clearer syntax with closures in Java SE 8.
The first style is the one suggested by Oracle. BufferedWriter doesn't throw checked exceptions, so if any exception is thrown, the program is not expected to recover from it, making resource recover mostly moot.
Mostly because it could happen in a thread, with the thread dieing but the program still continuing -- say, there was a temporary memory outage that wasn't long enough to seriously impair the rest of the program. It's a rather corner case, though, and if it happens often enough to make resource leak a problem, the try-with-resources is the least of your problems.
Option 4
Change your resources to be Closeable, not AutoClosable if you can. The fact that the constructors can be chained implies it isn't unheard of to close the resource twice. (This was true before ARM too.) More on this below.
Option 5
Don't use ARM and code very carefully to ensure close() isn't called twice!
Option 6
Don't use ARM and have your finally close() calls in a try/catch themselves.
Why I don't think this problem is unique to ARM
In all these examples, the finally close() calls should be in a catch block. Left out for readability.
No good because fw can be closed twice. (which is fine for FileWriter but not in your hypothetial example):
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(text);
} finally {
if ( fw != null ) fw.close();
if ( bw != null ) bw.close();
}
No good because fw not closed if exception on constructing a BufferedWriter. (again, can't happen, but in your hypothetical example):
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(text);
} finally {
if ( bw != null ) bw.close();
}
To concur with earlier comments: simplest is (2) to use Closeable resources and declare them in order in the try-with-resources clause. If you only have AutoCloseable, you can wrap them in another (nested) class that just checks that close is only called once (Facade Pattern), e.g. by having private bool isClosed;. In practice even Oracle just (1) chains the constructors and doesn't correctly handle exceptions partway through the chain.
Alternatively, you can manually create a chained resource, using a static factory method; this encapsulates the chain, and handle cleanup if it fails part-way:
static BufferedWriter createBufferedWriterFromFile(File file)
throws IOException {
// If constructor throws an exception, no resource acquired, so no release required.
FileWriter fileWriter = new FileWriter(file);
try {
return new BufferedWriter(fileWriter);
} catch (IOException newBufferedWriterException) {
try {
fileWriter.close();
} catch (IOException closeException) {
// Exceptions in cleanup code are secondary to exceptions in primary code (body of try),
// as in try-with-resources.
newBufferedWriterException.addSuppressed(closeException);
}
throw newBufferedWriterException;
}
}
You can then use it as a single resource in a try-with-resources clause:
try (BufferedWriter writer = createBufferedWriterFromFile(file)) {
// Work with writer.
}
The complexity comes from handling multiple exceptions; otherwise it's just "close resources that you've acquired so far". A common practice seems to be to first initialize the variable that holds the object that holds the resource to null (here fileWriter), and then include a null check in the cleanup, but that seems unnecessary: if the constructor fails, there's nothing to clean up, so we can just let that exception propagate, which simplifies the code a little.
You could probably do this generically:
static <T extends AutoCloseable, U extends AutoCloseable, V>
T createChainedResource(V v) throws Exception {
// If constructor throws an exception, no resource acquired, so no release required.
U u = new U(v);
try {
return new T(u);
} catch (Exception newTException) {
try {
u.close();
} catch (Exception closeException) {
// Exceptions in cleanup code are secondary to exceptions in primary code (body of try),
// as in try-with-resources.
newTException.addSuppressed(closeException);
}
throw newTException;
}
}
Similarly, you can chain three resources, etc.
As a mathematical aside, you could even chain three times by chaining two resources at a time, and it would be associative, meaning you would get the same object on success (because the constructors are associative), and same exceptions if there were a failure in any of the constructors. Assuming you added an S to the above chain (so you start with a V and end with an S, by applying U, T, and S in turn), you get the same either if you first chain S and T, then U, corresponding to (ST)U, or if you first chained T and U, then S, corresponding to S(TU). However, it would be clearer to just write out an explicit three-fold chain in a single factory function.
Since your resources are nested, your try-with clauses should also be:
try (FileWriter fw=new FileWriter(file)) {
try (BufferedWriter bw=new BufferedWriter(fw)) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
} catch (IOException ex) {
// handle ex
}
I just wanted to build on Jeanne Boyarsky's suggestion of not using ARM but making sure the FileWriter is always closed exactly once. Don't think there are any problems here...
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(text);
} finally {
if (bw != null) bw.close();
else if (fw != null) fw.close();
}
I guess since ARM is just syntactic sugar, we can't always use it to replace finally blocks. Just like we can't always use a for-each loop to do something that is possible with iterators.
I would say don't use ARM and go on with Closeable. Use method like,
public void close(Closeable... closeables) {
for (Closeable closeable: closeables) {
try {
closeable.close();
} catch (IOException e) {
// you can't much for this
}
}
}
Also you should consider calling close of BufferedWriter as it is not just delegating the close to FileWriter , but it does some cleanup like flushBuffer.
My solution is to do a "extract method" refactoring, as following:
static AutoCloseable writeFileWriter(FileWriter fw, String txt) throws IOException{
final BufferedWriter bw = new BufferedWriter(fw);
bw.write(txt);
return new AutoCloseable(){
#Override
public void close() throws IOException {
bw.flush();
}
};
}
printToFile can be written either
static void printToFile(String text, File file) {
try (FileWriter fw = new FileWriter(file)) {
AutoCloseable w = writeFileWriter(fw, text);
w.close();
} catch (Exception ex) {
// handle ex
}
}
or
static void printToFile(String text, File file) {
try (FileWriter fw = new FileWriter(file);
AutoCloseable w = writeFileWriter(fw, text)){
} catch (Exception ex) {
// handle ex
}
}
For class lib designers, I will suggest them extend the AutoClosable interface with an additional method to suppress the close. In this case we can then manually control the close behavior.
For language designers, the lesson is that adding a new feature could mean adding a lot others. In this Java case, obviously ARM feature will work better with a resource ownership transfer mechanism.
UPDATE
Originally the code above requires #SuppressWarning since the BufferedWriter inside the function requires close().
As suggested by a comment, if flush() to be called before close the writer, we need to do so before any return (implicit or explicit) statements inside the try block. There is currently no way to ensure the caller doing this I think, so this must be documented for writeFileWriter.
UPDATE AGAIN
The above update makes #SuppressWarning unnecessary since it require the function to return the resource to the caller, so itself does not necessary being closed. Unfortunately, this pull us back to the beginning of the situation: the warning is now moved back to the caller side.
So to properly solve this, we need a customised AutoClosable that whenever it closes, the underline BufferedWriter shall be flush()ed. Actually, this shows us another way to bypass the warning, since the BufferWriter is never closed in either way.
I don't know how to understand this:
{
if (inputStream **!= null**) {
inputStream.close();
from that example:
public class CopyLines {
public static void main(String[] args) throws IOException {
BufferedReader inputStream = null;
PrintWriter outputStream = null;
try {
inputStream = new BufferedReader(new FileReader("xanadu.txt"));
outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));
String l;
while ((l = inputStream.readLine()) != null) {
outputStream.println(l);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}}
inputStream is beeing closed when there is any data provided???
It means that whenever the try block is completed (successfully or not) it will try to close the streams (inputStream and outputStream) in the finally block but as the try block could fail while creating the instance of BufferedReader or PrintWriter, you need to check first if it is not null otherwise you will get a NPE.
You can consider using try-with-resouces statement to avoid having to check if null and calling close() explicitly such that it would simplify your code a lot.
try (BufferedReader inputStream = new BufferedReader(new FileReader("xanadu.txt"));
PrintWriter outputStream = new PrintWriter(new FileWriter("characteroutput.txt")) {
// your code here
}
If you're asking why this code is in finally block, then,
This is simply to ensure that the inputStream and outputStream will always be closed, no matter whether the code above encounters or doesn't encounters an exception.
How is it different.
The difference is during any exception. If any exception occurs, then instead of simply returning, it will ensure that both the streams are closed before returning the exception to the method that called this method.
bacause java's finally block is always executed, unless:
System.exit is called
or JVM crashes
This is a common practice to close stream, database, or any other similar connections in finally blocks. This ensures that the connections are always closed. Because if they aren't in finally block, and system is continuously encountering some or the other Excpetion then it will eventually run out of connections.
That's just to avoid null pointer exception. The functions are called only when object is not null.
In simple words, close function is only called when the objects are not null else if you call close() on object with null value, you will come across null pointer exception.
Interesting thing is the usage of finally, which is always called whether there is any exception or not.
When the execution reaches the finally block, it is first checked inputstream and outputstream are null or not then both the streams are closed to free the resources.
Please refer the link to check about try with finally : https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.2
In android, I am writing a file on clicking a button and on clicking next time, it saves the file and closes the buffered writer. But, I also want to implement functionality to close the buffered writer in onDestroy function. Before that I need to know if Bufferedwriter is already closed. How will I check if Buffered Writer is already closed?
In addition to that, does bufferedWriter.close() function set bufferedWriter to null?
Calling close method on already closed Writer has no impact.
Still, if you want to know if the Writer is closed, you can call writer.flush(), if it throws IOException then it means the Writer is already closed.
For your second question, closing a stream doesn't nullify the reference. You have to explicitly set it to null.
you can check if bufferredWriter not equal to null
if(bufferredWriter!=null)
{
bufferredWriter.close();
}
If you are using java7 or more then you need not to worry about closing the BufferredWriter
JDK 7 onwards you can make you of try with resource
for example
try(BufferredWriter bufferedWriter=new BufferredWriter())
{
//your code
}
catch(Exception e)
{
}
BufferedWriter vf = new BufferedWriter(new FileWriter("file"));
if (vf != null)
{
vf.close();
vf.close(); //won't cause any problem
}
you can close BufferedWriter as many times as you want if it is not null. So no need to check specifically if BufferedWriter is open or not.
Even better if you surround close statement in try/catch in case IOException occurs.
From javadocs
Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously closed stream has no effect.
And as explained by sidgate, closing a stream won't nullify the reference you have to assign it manually.
bufferedWriter.close() - Closes this writer. The contents of the buffer are flushed, the target writer is closed, and the buffer is released. Only the first invocation of close has any effect.
Refer this
Also, you can check like this
Define below 2 variables as instance variable
BufferedWriter bufferWriter;
boolean isOpen = false;
Then,
try {
if (!isOpen) {
bufferWriter = new BufferedWriter(new FileWriter(file, true));
bufferWriter.write(initialData);
isOpen = true;
}
bufferWriter.write(remainingData);
bufferWriter.flush();
Log.d(TAG, "written to file:" + file.getAbsolutePath());
} catch (IOException e) {
Log.v("IOException", e.toString());
}
This question already has answers here:
BufferedWriter not writing everything to its output file
(8 answers)
Closed 8 years ago.
So I'm using this function to write to text file, but the text file always ends up empty after executing. Can anyone see what the error might be? I've been stuck on this for a while.
public static void writeTextFile(String fileName, String s) {
FileWriter output = null;
try {
output = new FileWriter(fileName);
BufferedWriter writer = new BufferedWriter(output);
writer.write(s);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
// Ignore issues during closing
}
}
}
}
Just change your to include writer.close(); as given below
try {
output = new FileWriter(fileName);
BufferedWriter writer = new BufferedWriter(output);
writer.write(s);
writer.close();
}
//remaining code
The reason your data not saved in the file because , The Data is saved only if you call writer.flush(); And calling the writer.flush() method is enough to just save data. But you need to close the BufferedWriter() like writer.close(); to avoid resource leak. The close() calls flush() method for you before closing the stream.
After writing your output you should make sure to flush and close the socket, specially because you are using a buffered output.
writer.write(s);
writer.flush();
writer.close();
If you don't do that, the BufferedWriter will wait for additional data, but there does come none and the program execution is stopped suddenly. Using flush here is optional, as when closing it the flush is implicit, but personally I call it everytime I need to be sure that something goes out. Just like when on the toilet ;)
When you use a Buffer to write something, you must close him when you re end
writer.close();
Without closing bufferwriter you cannot see output on text file
try to add this code
writer.close()
I'm appending a line to a textfile each time a button is pressed. Currently I'm doing this each time the button is pressed:
...
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(f, true));
if (fileIsNew == true)
bw.write(firstLine);
bw.write(string);
bw.close();
Log.v("file", "written to file:" + f.getAbsolutePath());
} catch (IOException e) {
Log.v("IOException", e.toString());
}
...
I don't think it's really a good idea to close the bufferedwriter after each line as the purpose of a bufferedWriter is to buffer the output, right?
So when should I call bw.close() ?
And should I create the new BufferedWriter in some kind of init()?
I think it's inefficient to create a new BufferedWriter each time the button is pressed.
You can declare it as a member field, create it upon first press on the button, by setting a flag, and keep it open.
On each press, call write() and then flush() (to avoid content loss).
BufferedWriter bw;
boolean isOpen = false;
// ..
try {
if (!isOpen) {
bw = new BufferedWriter(new FileWriter(logFile, true));
bw.write(firstLine);
isOpen = true;
}
bw.write(string);
bw.flush();
Log.v("file", "written to file:" + logFile.getAbsolutePath());
} catch (IOException e) {
Log.v("IOException", e.toString());
}
In this article you can find that, in a good programming style:
The short answer is that you should create a FileWriter instance with the append flag set to true, like this:
BufferedWriter bw = new BufferedWriter(new FileWriter("checkbook.dat", true));
Have fun
You should always close the buffered reader if you are not going to use it again, which is the case here. Otherwise, you leave to the GC to decide when to collect the object, and the resource will be disposed at that time.
So the short answer is: ALWAYS!
You basically answered the question yourself, the whole purpose of it it IO buffering. Usually you'd open it once, could be in init or whenever it is first needed, you flush and close it when you're done writing all the data. Note however, that unless you explicitly call flush(), the content may be written not at the exact moment you call write() to it but buffered for later output.