how to properly close resource streams in case of exceptions - java

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();

Related

IO bufferReader vs nio Files.newBufferedReader CharsetDecoder leniency on MalformedInput

I have a text file that contains invalid "UTF-8" charactor and this causing my app to throw MalformedInputException. I use Files.newBufferedReader to create BufferReader.
Path path = FileSystems.getDefault().getPath(inputDirectory, fileName);
BufferedReader br = Files.newBufferedReader(path, Charset.defaultCharset());
And this seems to be strict on the character encoding. I did some digging and found online that we can improve the leniency by overriding CharactorDecoder default action by .onMalformedInput(CodingErrorAction.REPLACE). This seems to be fixing the issue.
Then out of curiosity I used java IO BufferedReader to Read the same file.
fr = new FileReader(file);
br = new BufferedReader(fr);
This seems to have no issue on the invalid character and read the file without any issue.
So I looked at the code of both Files.newBufferedReader and new BufferedReader(fr). This is how they both implemented
Files.newBufferedReader:
public static BufferedReader newBufferedReader(Path path, Charset cs)
throws IOException
{
//onMalformedInput is not overridden. Thus strict decoding
CharsetDecoder decoder = cs.newDecoder();
//Look at how the InputStreadReader created. The decoder being passed
Reader reader = new InputStreamReader(newInputStream(path), decoder);
return new BufferedReader(reader);
}
IO BuffereReader
//Creating File Reader
FileReader fr = new FileReader(file);
--------------------------------------------------------------------
//File Reader constructor
public FileReader(File file) throws FileNotFoundException {
//Calls it's supper constructor InputStreamReader
super(new FileInputStream(file));
}
-----------------------------------------------------------
//InputStreamReader Constructor
public InputStreamReader(InputStream in) {
super(in);
try {
//This where I don't understand
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
}
As you can see they both uses StreamDecoder.forInputStreamReader. I know why Files.newBufferedReader has strict decoder. But I am trying to understand where in IO BufferredReader, it's defined to do lenient decoding.
Would really appreciate if some can help me understand this.
The lenient decoding should actually be done by FileReader. I can't find any part of the documentation that specifies this, but digging into its code it uses onMalformedInput(CodingErrorAction.REPLACE) too. I'm not sure if it can be trusted to be the same way in all JDK implementations though.

Is it incorrect to open a file for writing before it has been closed for reading?

I am refactoring a small tool which needs to iterate over a list of files and modify them on the fly.
At the moment it performs the modification operation in one method, which means it reads the file to memory, modifies the content within memory, and writes that content back to the same file location.
It is doing so all within a couple of try-with-resource statements. However, this means that the 'open for write' gets done before the read is closed.
I provide here below a small approximation (see method "correctTxt").
To test that, please create a file "FileQuestion.txt"
with text such as
The quick brown elephant jumps over the lazy dog
public class Demo
{
public static void main(String[] args) throws Exception
{
final File txtFile = new File("FileQuestion.txt");
correctTxt(txtFile);
}
static void correctTxt(File txtFile) throws IOException
{
try (BufferedReader reader = new BufferedReader(new InputStreamReader (new BufferedInputStream(new FileInputStream(txtFile))))) {
String line = reader.readLine();
if (line!=null) {
line = line.replace("elephant", "fox");
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(txtFile))) {
bos.write(line.getBytes());
bos.flush();
}
}
}
}
}
It works. It is all done in a single process (single thread).
The question is,
Is it fundamentally incorrect to perform the write operation before the close of the read, in the way that is done in the method correctTxt ?
Note: It is not intended, after the first read, that any further read be done.
Good question. I'd say it's probably technically not a problem, but... I see is that the scope of the try-with is unnecessarily big and if you would reduce the scope to where it's needed, you wouldn't even be in this situation.
See this version of the correctTxt with minimized try-with scopes
static void correctTxt(File txtFile) throws IOException {
String line;
try (BufferedReader reader = new BufferedReader(new InputStreamReader (new BufferedInputStream(new FileInputStream(txtFile))))) {
line = reader.readLine();
}
if (line!=null) {
line = line.replace("elephant", "fox");
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(txtFile))) {
bos.write(line.getBytes());
bos.flush();
}
}
}

Java: Unable to read file using FileReader [duplicate]

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).

Java error: Default constructor cannot handle exception type FileNotFound Exception

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).

Closing nested Reader

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.

Categories