4

I have closed file steam in try/finally, but code analysis warns me:

  • Possible failure to close a FileOutputStream
  • Possible failure to close a PrintWriter
  • Possible failure to close an OutputStreamWriter

How can failure happen? How can I ensure the FileStream is closed?

public void writeFile(String filepath)
{
    BufferedWriter bw = null;
    PrintWriter pw = null;
    try {
        File file = new File(filepath);
        bfw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
        pw = new PrintWriter(bfw);

     //do something

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        try{
            bfw.close();
            pw.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
tensor
  • 43
  • 2

3 Answers3

3

If you are using Java-7 and above then you can use try with resources

File file = new File(filepath);
try(BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
    PrintWriter pw = new PrintWriter(bfw);)
{
    ...
}
catch(Exception exception) //This is optional
{
    exception.printStackTrace();
}

You can use catch and finally blocks with try-with-resources statement just like an ordinary try statement.

Hope this helps!

N00b Pr0grammer
  • 4,503
  • 5
  • 32
  • 46
  • And you can leave out catch and finally blocks altogether because an implicit finally is already present. – daniu Mar 29 '18 at 04:12
2

How can failure happen?

See your finally block:

finally{
    try{
        bfw.close();   <== exception occured here
        pw.close();    <== this is not execute
    }catch(Exception e){
        e.printStackTrace();
    }
}

What if an exception occurs in bfw.close()? pw.close() will never execute. And this leads to a resource leak.

How can I ensure the FileStream is closed?

Someone already pointed out using try/catch/finally inside finally. But if you don't like to see so many try catch finally I would suggest you to use a library like Apache Commons IO.

Solution:

try {

   ........
} finally {
    IOUtils.closeQuietly(bfw);
    IOUtils.closeQuietly(pw);
}

And yes, you always have try-with-resources if using Java 7 or above.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
VedantK
  • 9,728
  • 7
  • 66
  • 71
  • 1
    I think the mix of Am_I_Helpful and VedX is the answer.It is good to do null check before close() and catch each exception happening in close() in case of resource leak. VedX is good answer with clear explanation but it cannot handle exception case. So I choose this as the answer – tensor Mar 29 '18 at 06:40
  • Are you aware that `IOUtils` from `commons-io` has open security vulnerabilities, @tensor ? – N00b Pr0grammer Mar 31 '18 at 02:58
0

If exception happens when closing bw you will not close pw. Try this:

finally{
    try{
        bw.close();
    } catch(Exception e){
        e.printStackTrace();
    } finally {
        pw.close();
    }
}
Sai Kishore
  • 326
  • 1
  • 7
  • 16
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • 1
    as a matter of fact pw.close() internally closes underlying stream - bw. Best solution (except java 7) is: pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))); – Evgeniy Dorofeev Mar 29 '18 at 04:09