When reading from a text file, one typically creates a FileReader and then nests that in a BufferedReader. Which of the two readers should I close when I'm done reading? Does it matter?
FileReader fr = null;
BufferedReader br = null;
try
{
fr = new FileReader(fileName);
br = new BufferedReader(fr);
// ...
}
finally
{
// should I close fr or br here?
}
I'm a little paranoid when it comes to exception-safety. What happens when the BufferedReader constructor throws an exception? Does it close the nested reader? Or is it guaranteed not to throw?
Generally, close() on the outermost stream wrapper will call close() on the wrapped streams. However, if you think it's likely that a constructor will throw an exception, make liberal use of the Closeable interface.
FileReader fr = new FileReader(fileName);
Closeable res = fr;
try {
BufferedReader br = new BufferedReader(fr);
res = br;
} finally {
res.close();
}
So, even if the JVM ran out of heap space for the buffer and threw an error, you wouldn't leak a file handle.
For Java 7 and above use try-with-resources:
try (FileReader fr = new FileReader(fileName);
BufferedReader br = new BufferedReader(fr)) {
// do work
}
Closing only the BufferedReader is enough, cause it wraps the FileReader. If you look at the source code of BufferedReader you will see that the close method, closes the wrapped stream.
Close the BufferedReader in a finally block.
If you call the BufferedReader's close method, the BufferedReader will call the FileReader's close method. Thus both close method's are called. More precisely the BufferedReader will do nothing BUT calling the FileReader's close method. Thus it does not matter at all. Though I think it is good practice too call the BufferedReader's close method.
Nothing is guaranteed not to throw. Because the buffer is allocated it may throw OutOfMemoryError. I usually separate my code into 2 sections: acquire resources and then use resources. Each section usually has unique cleanup needs
Here is the code to illustrate:
// Acquire resources section.
final FileReader fr = new FileReader( fileName );
BufferedReader br = null;
try
{
br = new BufferedReader(fr);
}
finally
{
if ( br == null )
{
// Note that you are closing the fr here
fr.close( );
}
}
// Use resources section
try
{
// ... use br
}
finally
{
// Now that br is safely constructed, just all its close
br.close( );
}
And I agree with you, there is nothing worth than silently loose a file handler in the long running server application.
Related
In this code I read a text file, when BufferedReader is closed by "try-resource" block so the InputStreamReader does, then can I guarantee all the resources are closed like this?
try(final BufferedReader br = new BufferedReader(new InputStreamReader(new
FileInputStream(file), charset))) {
String line = null;
while((line = br.readLine()) != null) {
builder.append(line);
}
}
In this other example, I write a text file, as is written, are all the resources closed in the end? Is it mandatory to call flush()?
try(final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream(file), charset))) {
bw.write(text);
bw.flush();
}
Yes, the outermost streams call their inner streams' close() methods, so you only need to call the outermost stream.
You don't need to call flush(), the streams will flush when necessary and before being closed. Remove that and the code will look perfect.
fortify is complaining about the following code:
protected void doStuff() throws Exception{
try (CSVReader csvReader = new CSVReader(new FileReader(file))) {
...
String[] read;
read = csvReader.readNext();
...
}
}
in the case that FileReader throws an exception. Im new to java, its unclear to me why the try with resources block doesnt handle the case. How to handle this?
It's always a good idea to close the lower level reader instance first and then close the wrapper level instance to avoid the memory leak.
So first close the instance of fileReader and then close instance of
CSVReader.
FileReader fileReader= new FileReader(file)
CSVReader csvReader = new CSVReader(fileReader)
....
...
fileReader.close();
csvReader.close();
I'm trying to use read method for jTextArea from BufferedReader. It works and my text appears in jTextArea successfully. but after using read method it makes BufferedReader null. Here is my example code:
private void Calculate() throws IOException{
BufferedReader br = new BufferedReader(new FileReader(file)) ;
jTextArea.read(br, "jTextArea");
System.out.println(br.readLine());
}
When I comment out this "jTextArea.read(br, "jTextArea");" println works properly and prints out the first line. But in normal case It prints null.
P.S: "file" is my instance variable. There is no problem with this variable, it works properly too.
BufferedReader br object has reached its end after being read. So, not the br is null, but it's current line, which you're trying to read by br.readLine(). Otherwise a NullPointerException would be thrown on calling br.readLine().
You need to reinitialize BufferedReader and got the first line printed:
private void Calculate() throws IOException {
BufferedReader br = new BufferedReader(new FileReader(file));
jTextArea.read(br, "jTextArea");
br = new BufferedReader(new FileReader(file));
System.out.println(br.readLine());
}
I'm trying to read input from a file to be taken into a Java applet to be displayed as a Pac-man level, but I need to use something similar to getLine()... So I searched for something similar, and this is the code I found:
File inFile = new File("textfile.txt");
FileInputStream fstream = new FileInputStream(inFile);//ERROR
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
The line I marked "ERROR" gives me an error that says "Default constructor cannot handle exception type FileNotFoundException thrown by implicit super constructor. Must define an explicit constructor."
I've searched for this error message, but everything I find seems to be unrelated to my situation.
Either declare a explicit constructor at your subclass that throws FileNotFoundException:
public MySubClass() throws FileNotFoundException {
}
Or surround the code in your base class with a try-catch block instead of throwing a FileNotFoundException exception:
public MyBaseClass() {
FileInputStream fstream = null;
try {
File inFile = new File("textfile.txt");
fstream = new FileInputStream(inFile);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
// Do something with the stream
} catch (FileNotFoundException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
} finally {
try {
// If you don't need the stream open after the constructor
// else, remove that block but don't forget to close the
// stream after you are done with it
fstream.close();
} catch (IOException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
}
}
Unrelated, but since you are coding a Java applet, remember that you will need to sign it in order to perform IO operations.
You need to surround your code with try and catch as follows:
try {
File inFile = new File("textfile.txt");
FileInputStream fstream = new FileInputStream(inFile);//ERROR
} catch (FileNotFoundException fe){
fe.printStackTrace();
}
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
This is guesswork as we don't have the complete code.
From the Javadoc:
public FileInputStream(File file) throws FileNotFoundException
It means that when you do a new FileInputStream() like you do, it can come back with a FileNotFoundException. This is a checked exception, that you need to either rethrow (i.e. add 'throws FileNotFoundException' in the method where you do the new) or catch (see other try/catch responses).
I have two files to be read using same variables for the task with the following code:
try {
FileInputStream fis = new FileInputStream(filename1);
InputStreamReader isr = new InputStreamReader(fis, "UTF8");
BufferedReader br = new BufferedReader(isr);
String line="";
while((line=br.readLine())!=null){
System.out.println(line);
}
// Do i need to add these 3 statements ...
//br.close();
//isr.close();
//fis.close();
//Without the above 3 statements also the code works fine ...
fis = new FileInputStream(filename2);
isr = new InputStreamReader(fis, "UTF8");
br = new BufferedReader(isr);
line="";
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
isr.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
The filereading in java doesn't bother about closing the opened stream and releasing any system resources associated with it for the first file filename1?
No exceptions thrown.
So you have a resource leak which won't cause a problem for you unless you;
attempt to delete the file on Windows (as the file is still open)
do this many times in which case you might run out of file handles.
The code works, but it is not a good practice.
Java will automatically close the first file when the garbage collector decides to run and to deallocate your first FileInputStream object. This might happen at any time after you lose the last reference to the object, but might even not happen at all, depending on your memory conditions.
If you are using Java 7, you can use the try with resources construct, which will call close for you:
try (FileInputStream fis = new FileInputStream(filename1);
InputStreamReader isr = new InputStreamReader(fis, "UTF8");
BufferedReader br = new BufferedReader(isr)) {
// Code...
}
Once you created new instance for the StreamReader, Automatically call the garbage collection for the previously opened stream.