How to handle IOException when closing bufferedReader - java

Hi I am learning about Exceptions in Java and I encountered a problem with this situation.
public static void main(String[] args){
String path = "t.txt";
BufferedReader br = null;
try{
br = new BufferedReader(new FileReader(path));
StringBuilder sbd = new StringBuilder();
String line = br.readLine();
while(line != null){
sbd.append(line);
sbd.append(System.lineSeparator());
line = br.readLine();
}
String result = sbd.toString();
System.out.print(result);
}catch(IOException e){
System.out.println(e.getMessage());
}finally{
if (br != null)
br.close(); //Here it says unreported exception IOException; must be caught or declared to be thrown
}
}
when I call method close() to close the bufferedReader, it says unreported exception IOException; must be caught or declared to be thrown.
I know that JAVA 7 provides a pretty easy way to do the clean-up with
try(br = new BufferedReader(new FileReader(path))){
//....
}
but prior to JAVA 7, what can I do with this situation? adding "throws IOException" right next to the main function declaration is a way to fix that but is it a little bit complicated since I have had a catch section to catch IOExceptions

You wrapped it into another try-catch
}finally{
if (br != null)
try {
br.close(); //Here it says unreported exception IOException; must be caught or declared to be thrown
} catch (Exception exp) {
}
}
Now, if you care or not is another question. To my mind, your intention here is to make all best effort to close the resource. If you want, you could use flag and set it to true in the parent catch block (indicating that any following errors should be ignored) and if it's false in the close catch block, display an error message, for example...
boolean hasErrored = false;
try {
//...
}catch(IOException e){
e.printStackTrace();
hasErrored = true;
}finally{
if (br != null)
try {
br.close(); //Here it says unreported exception IOException; must be caught or declared to be thrown
} catch (Exception exp) {
if (!hasErrored) {
// Display error message...
}
}
}

prior to JAVA 7, what can I do with this situation?
You can add a try-catch in the finally block like,
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
// Handle the IOException on close by doing nothing.
}
}
}

add another try catch block
...
if(br != null)
try{
br.close();
} catch (IOException io){
}

I generally code it thus:
} finally {
if (br != null) {
try {
br.close();
} catch(IOException ioe) {
// do nothing
}
}
}
In fact, I once wrote a util class containing methods such as closeStream(final InputStream stream), closeStream(final OutputStream stream), closeReader(final Reader reader), etc that hides all this stuff, since you end up using it all the time.

This is approximately how try-with-resources closes resources
BufferedReader br = new BufferedReader(new FileReader(path));
IOException ex = null;
try {
br.read();
// ...
} catch(IOException e) {
ex = e;
} finally {
try {
br.close(); // close quietly
} catch (IOException e) {
if (ex != null) {
ex.addSuppressed(e);
} else {
ex = e;
}
}
}
if (ex != null) {
throw ex;
}

Related

Why I can't test for FileNotFoundException in java JUnit 4.13

I am facing some difficulties with testing constructor of my class using JUnit 4.13. What I am trying to do is to test that constructor is throwing FileNotFoundExeption when I pass wrong file name.
This is my constructor (parameter 'file' is name of file where I store languages):
public LanguageManager(String file) {
this.languages = new ArrayList<Language>();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
String line;
while((line = in.readLine()) != null) {
line = line.trim();
if (line.equals("") || line.startsWith("#"))
continue;
Language j = new Language(line);
this.languages.add(j);
}
in.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
This is my function for testing this constructor:
#Test(expected=FileNotFoundException.class)
public void testLanguageManager() {
LanguageManager ajm = new LanguageManager("non_existing_file.txt");
}
I suspect that there is problem with try catch block in constructor but can't figure out what I am doing wrong. Any help is appreciated.

Using FileInputStream compile error says variable is uninitialized

Can somebody tell me what am I doing wrong in the below java code ? It doesn't compile and gives me compilation error.
import java.io.*;
public class ShowFile {
public static void main(String[] args) {
int i;
FileInputStream Fin;
try {
Fin = new FileInputStream("C:\\Users\\cbr\\Desktop\\test.txt");
} catch (FileNotFoundException exp) {
System.out.println("exception caught" + exp);
}
try {
do {
i = Fin.read();
System.out.print((char) i);
} while (i != -1);
} catch (IOException exp) {
System.out.println("Exception caught" + exp);
}
finally {
try {
Fin.close();
} catch (IOException exp) {
System.out.println("Exception caught" + exp);
}
}
}
}
while the below code compiles. You can see both initialization are within try block.
import java.io.*;
class ShowFile2 {
public static void main(String args[]) {
int i;
FileInputStream fin;
// First make sure that a file has been specified.
try {
fin = new FileInputStream("C:\\Users\\cbr\\Desktop\\test.txt");
} catch (FileNotFoundException exc) {
System.out.println("File Not Found");
return;
}
try {
// read bytes until EOF is encountered
do {
i = fin.read();
if (i != -1) {
System.out.print((char) i);
}
} while (i != -1);
} catch (IOException exc) {
System.out.println("Error reading file.");
}
try {
fin.close();
} catch (IOException exc) {
System.out.println("Error closing file.");
}
}
}
The problem is, that if new FileInputStream("C:\\Users\\cbr\\Desktop\\test.txt"); throws an exception, your variable will not be initialized in the second part of your method. This is not allowed. Object members will be initialized to null when the object is created, but this is not the case for local variables: they must be initialized explicitly.
A quick fix (but read on for a better fix) would be to initialize your variable (to null) when you are defining it:
FileInputStream fin = null;
This will solve your compilation error, however, you will get NullPointerExceptions when an exception is thrown in the first catch block.
A better solution is to put your error handling logic in the same place: if creating the FileInputStream fails, you don't want to read bytes from it anyway. So you can use a single try-catch block:
try {
fin = new FileInputStream("C:\\Users\\cbr\\Desktop\\test.txt");
// Read bytes from fin.
...
} catch (IOException e) {
// handle exception
...
}
Final advice: to make sure that your input stream is closed in all circumstances, you can use a try-with-resources block:
try (fin = new FileInputStream("C:\\Users\\cbr\\Desktop\\test.txt")) {
// Read bytes from fin.
...
} catch (IOException e) {
// handle exception
...
}
It does compile because the ShowFile2 class contains return in the catch block: this will ensure that the variable fin will be always initialized.
In the first class you caught the exception and you continue the execution of your program.

Why is eclipse complaining when I try to close BufferedReader in finally block?

Here is my code:
public static String readFile()
{
BufferedReader br = null;
String line;
String dump="";
try
{
br = new BufferedReader(new FileReader("dbDumpTest.txt"));
}
catch (FileNotFoundException fnfex)
{
System.out.println(fnfex.getMessage());
System.exit(0);
}
try
{
while( (line = br.readLine()) != null)
{
dump += line + "\r\n";
}
}
catch (IOException e)
{
System.out.println(e.getMessage() + " Error reading file");
}
finally
{
br.close();
}
return dump;
So eclipse is complaining about an unhandled IO exception caused by br.close();
Why would this cause an IO exception?
My second question is why eclipse doesn't complain about the following code:
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
try{
// open input stream test.txt for reading purpose.
is = new FileInputStream("c:/test.txt");
// create new input stream reader
isr = new InputStreamReader(is);
// create new buffered reader
br = new BufferedReader(isr);
// releases any system resources associated with reader
br.close();
// creates error
br.read();
}catch(IOException e){
// IO error
System.out.println("The buffered reader is closed");
}finally{
// releases any system resources associated
if(is!=null)
is.close();
if(isr!=null)
isr.close();
if(br!=null)
br.close();
}
}
}
I'd appreciate it if you kept the explanation in Laymen's terms if possible. Thanks for the help in advance
Both code examples should have compiler errors complaining about an unhandled IOException. Eclipse shows these as errors in both code examples for me.
The reason is that the close method throws an IOException, a checked exception, when called in the finally block, which is outside a try block.
The fix is to use a try-with-resources statement, which is available in Java 1.7+. The resources declared are implicitly closed.
try (BufferedReader br = new BufferedReader(new FileReader("dbDumpTest.txt")))
{
// Your br processing code here
}
catch (IOException e)
{
// Your handling code here
}
// no finally necessary.
Prior to Java 1.7, you need to wrap the calls to close() in their own try-catch blocks inside the finally block. It's a lot of verbose code to ensure that everything is closed and cleaned up.
finally
{
try{ if (is != null) is.close(); } catch (IOException ignored) {}
try{ if (isr != null) isr.close(); } catch (IOException ignored) {}
try{ if (br != null) br.close(); } catch (IOException ignored) {}
}

How to close a RandomAccessFile

I'm trying to close a RandomAccessFile but resource remain busy.
Code:
public boolean isOpen(RandomAccessFile f) {
try {
f.length() ;
return true ;
}
catch (IOException e) {
return false ;
}
}
this.rfmFile = new File(filePath);
try {
this.rfmRandomAccessFile = new RandomAccessFile(rfmFile, "rws");
} catch(Exception e){
}finally{
this.rfmRandomAccessFile.close();
}
while(!isOpen(this.rfmRandomAccessFile));
log.debug("I Finally Closed this RAF");
Log is not showed and thread goes in loop.
When I try to access to my resource from shell it gives me "Device or Resource busy".
The only way to access is kill java process.
When you are trying to access the RandomAccessFile length(), method, it is already closed and thus you cannot access it anymore.
You probably want to use the length() method of File. Your loop cannot work as the RandomAccessFile was already closed.
But I must admit I am clueless on the low level reason why rfmRandomAccessFile would not really be closed. It could be a side effect of your strange loop trying to get the size of a closed file.
[edit:]Could not reproduce your issue with the following piece of code:
package com.company;
import java.io.*;
public class Main {
public static void main(String[] args) {
File file = new File("foobar.txt");
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile(file, "rws");
randomAccessFile.write(new byte[]{'f'});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(randomAccessFile !=null){
try {
randomAccessFile.close();
} catch (IOException e) {
//doh!
}
}
}
FileReader reader = null;
try {
reader = new FileReader(file);
char read = (char) reader.read();
System.out.println("what was written: "+read);
System.out.println("file size: "+file.length());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader !=null){
try {
reader.close();
} catch (IOException e) {
//doh!
}
}
}
}
}

Learning handling exceptions, can't figure out this FileNotFoundException

I'm a beginner still, and currently learning about handling exceptions. The exercise in my book I'm trying to figure out tells me to add a Finally block to close out the file I opened, and I don't understand what I'm doing wrong. Keep in mind the file name and path are fake but here is what I have:
public static String readLineWithFinally()
{
System.out.println("Starting readLineWithFinally method.");
RandomAccessFile in = new RandomAccessFile("products.ran", "r");
try
{
String s = in.readLine();
return s;
}
catch (IOException e)
{
System.out.println(e.toString());
return null;
}
finally
{
try
{
in.close();
}
catch (Exception e)
{
System.out.println("Generic Error Message");
}
}
}
To add on to Taylor Hx's answer, you can take advantage of Java 7's try-with-resources construct to avoid having to use finally altogether in your case.
public static String readLineWithFinally() {
System.out.println("Starting readLineWithFinally method.");
try (RandomAccessFile in = new RandomAccessFile("products.ran", "r")) {
return in.readLine();
} catch (IOException e) {
System.out.println(e.toString());
return null;
}
}
You'll also want to be certain that your usage is consistent with what the API mandates for RandomAccessFile.
The code that you posted shouldn't compile, as RandomFile(String, String) can possibly throw FileNotFoundException. As such, we must include it in the try block.
System.out.println("Starting readLineWithFinally method.");
RandomAccessFile in = null;
try {
in = new RandomAccessFile("products.ran", "r");
String s = in.readLine();
return s;
} catch (IOException e) {
System.out.println(e.toString());
return null;
} finally {
try {
if(in != null) {
in.close();
}
} catch (Exception e) {
System.out.println("Generic Error Message");
}
}
Keep in mind the file name and path are fake but here is what I have:
That is why you will have a FileNotFoundException while creating RandomAccessFile("products.ran", "r") with read access mode "r".
From the documentation: RandomAccessFile(String name, String mode)
This constructor throws a FileNotFoundException if the mode is
"r" but the given string does not denote an existing regular file,
or if the mode begins with "rw" but the given string does not denote
an existing, writable regular file and a new regular file of that name
cannot be created, or if some other error occurs while opening or
creating the file

Categories