The standard way of handling file reading and writing in java goes something like this:
try
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file.dat"));
oos.writeObject(h);
oos.close();
}
catch (FileNotFoundException ex)
{
}
catch (IOException ex)
{
}
But I'm bothered by that code, because it could be possible here that the file is never closed if an exception is thrown. Sure we could add a finally clause and initialise the ObjectOutputStream outside the try block. However, when you do that you need to add another try/catch block INSIDE the finally block again...that's just ugly. Is there a better way of handling this problem?
use apache commons io
http://commons.apache.org/proper/commons-io/
look at their FileUtils class. Full of gold. Gold I say....
This is not the standard way at all. This is the bad way.
The way I use most of the time is this one :
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new FileOutputStream("file.dat"));
// use out
}
finally {
if (out != null) {
try {
out.close();
}
catch (IOException e) {
// nothing to do here except log the exception
}
}
}
The code in the finally block can be put in a helper method, or you can use commons IO to close the stream quietly, as noted in other answers.
A stream must always be closed in a finally block.
Note that JDK7 will make it much easier with the new syntax, which will automatically close the stream at the end of the try block :
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file.dat"))) {
// use out
}
This why I use commons-io's IOUtils.closeQuitely(...)
try
{
...
}
finally
{
IOUtils.closeQuietly(costream);
}
try
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file.dat"));
oos.writeObject(h);
//oos.close(); // glow coder removed
}
catch (FileNotFoundException ex)
{
}
catch (IOException ex)
{
}
// glowcoder adds:
finally {
try {
oos.close();
}
catch(IOException ex) {
// dammit we tried!
}
}
add this finally:
finally{
if(oos != null)
oos.close();
}
Related
I would like to make you think about a tiny problem using the method printStackTrace(PrintWriter s). I need to use it in append mode.
The following example is explaining what I mean:
try {
} catch (Exception e) {
try {
e.printStackTrace(new PrintWriter(new FileWriter("mylog.txt", true)));
} catch (IOException ioe) {
System.out.println("I can't open the file mylog.txt");
}
}
Note that
new FileWriter("mylog.txt", true);
is the way I open the file (and create it the first time because it doesn't exist) in append mode.
The result is that in the file there is only the last exception and not a series of exceptions. One time it occurred that the method opened the file in which it didn't write anything.
How can I solve this problem?
Thank you.
Adding to what krzyk mentioned
Per OutputStreamWriter.close() : 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.
As mentioned, if you do not call close and this try{}catch is getting fired frequently, you are not flushing content to file.
It should written like
try {
} catch (Exception e) {
try {
FileWriter fw = new FileWriter("mylog.txt", true)
e.printStackTrace(new PrintWriter(fw));
fw.close();
} catch (IOException ioe) {
System.out.println("I can't open the file mylog.txt");
}
}
A better approach will be
FileWriter fw = new FileWriter("mylog.txt", true);
PrintWriter pw = new PrintWriter(fw);
try {
} catch (Exception e) {
try {
e.printStackTrace(pw);
} catch (IOException ioe) {
System.out.println("I can't open the file mylog.txt");
}
}finally {
pw.close();
fw.close();
}
You should close the created Writers, not closing it might cause the problems you describe.
try (PrintWriter writer = new PrintWriter(new FileWriter("mylog.txt", true))) {
e.printStackTrace(writer);
}
A beginners book on Java has the following code in it. This book also explains about exceptions very well, and since I understood how exception works, I got a question about the following code.
For some reason if FileWriter class throws an exception, writer.close() wouldn't be executed. Therefore I think the best place to close the writer object is in a finally block. Even prior to this I have seen many code written like this, where the resource will be closed in the try block itself. I think there is no point in doing so. Only when there is no exception the resource will be closed.
Am I wrong? What is the best way to close resources in java. Should we never write code like the following?
public static void main(String[] args) {
try{
FileWriter writer = new FileWriter("file.txt");
writer.write("i am writing");
writer.close();
}catch(IOException e){
ex.printStackTrace();
}
}
I agree with #cyber-rookie, it is probably best to close resources in a finally block.
Java 7 introduced "try-with-resources" in order to cut down on programming mistakes...
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
You can now write...
try (FileWriter writer = new FileWriter("file.txt")) {
writer.write("i am writing");
} catch (IOException e) {
e.printStackTrace();
}
The compiler will add the extra code to close the writer at the end of the block for you
If your are using Java 7, the best approach is to use try with resource. See https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
try (FileWriter writer = new FileWriter("file.txt")) {
writer.write("i am writing");
}
you are right, resource should be closed in finally block.
as of java 7 you can use try-with-resource also as :
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly if these resources implements AutoCloseable interface.
In my experience we would utilise the finally clause of a try-catch:
public static void main(String[] args) {
FileWriter writer = null;
try {
writer = new FileWriter("file.txt");
writer.write("i am writing");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
PS: Place this in separate method and throw the exception, let the class using this handle exceptions.
Answer to a comment to add multiple resources in a try with resource block:
try(FileWriter writer = new FileWriter("file.txt"); BufferedReader reader = new BufferedReader(new FileReader("file.txt"))){
// you can put many AUTOCLOSEABLE objects in try with resource. Just seperate them with ";"
} catch (IOException e) {
e.printStackTrace();
}
At work (Java 6), we close the resources in the TRY block then also do a defensive close in the FINALLY block.
BufferedReader bufferedReader;
try {
//initialize and do something with the bufferedReader
bufferedReader.close();
} catch (FileNotFoundException ex) {
// notify the user
} catch (IOException ex) {
// notify the user
} finally {
if (bufferedReader != null) {
try {
//defensive close
bufferedReader.close();
} catch (IOException ex) {
// this will be thrown if bufferedReader is already closed (in Try block, so can be leave to blank
}
}
}
I am using the following method to read from the internal storage:
private void deserialize(ArrayList<Alias>arrayList) {
try {
FileInputStream fis = openFileInput(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
arrayList = (ArrayList<Alias>)ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
It reads the content of the file "filename" to the "arrayList".
The "serialize" method is as follows:
void serialize(ArrayList<Alias>arrayList) {
FileOutputStream fos;
try {
fos = openFileOutput(filename, Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(arrayList);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
The problem is that I whenever I run my program again, the "arrayList" is empty. So I guess I am opening the file in wrong input mode.
My aim is to first get the array from the file, then modify it within the app, and then write the modified array back to the file.
Can someone please help me with my problem?
Thanks!
Can you post your pice of your source code? I think the way which you used to parse file content get issue.
Read here:
Android ObjectInputStream docs
I read that the method readObject() read the next object...i this that you must iterate with something like this:
MediaLibrary obj = null;
while ((obj = (MediaLibrary)objIn.readObject()) != null) {
libraryFromDisk.add(obj);
}
I submitted my code for Veraocode Security Testing tool and i got this Improper Resource Shutdown or Release at the below code:
//This function is used to print trace in the in the LogFile for debugging purpose
PrintWriter f;
try {
f = new PrintWriter(new BufferedWriter(new FileWriter(fileName,true)));//issue at this line
synchronized(this) {
f.println(new StringBuffer(dateString).append("<").append(Thread.currentThread().getName()).append(">").append(traceLog).toString());
}
f.close();
checkFileSize();
}catch(IOException e){
e.printStackTrace();
}
Someone please help me on this...
You need to close your PrintWriter.
f.close();
try {
f = new PrintWriter(new BufferedWriter(new FileWriter(fileName,true)));//issue at this line
synchronized(this) {
f.println(new StringBuffer(dateString).append("<").append(Thread.currentThread().getName()).append(">").append(traceLog).toString());
}
checkFileSize();
}catch(IOException e){
e.printStackTrace();
} finally {
if (f != null) {
f.close();
}
}
Resources should be closed in finally clause. So that they definitely get executed. Because if you put closing code in try, and some exception occurs before the closing line. The resource doesn't get closed properly.
Also if you are using JDK-7, have a look at try-with-resources.
You need to close the PrintWriter in catch block also Or create finally block and close the resource.
}catch(IOException e){
e.printStackTrace();
f.close();
}
OR
finally {
if (f != null) {
f.close();
}
}
Basically, I want to open a file, read some bytes, and then close the file. This is what I came up with:
try
{
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
try
{
// ...
inputStream.read(buffer);
// ...
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try
{
inputStream.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Maybe I'm spoiled by RAII, but there must be a better way to do this in Java, right?
If you have the same exception handling code for IOException and FileNotFoundException then you can rewrite your example in a more compact way with only one catch clause:
try {
InputStream input = new BufferedInputStream(new FileInputStream(file));
try {
// ...
input.read(buffer);
// ...
}
finally {
input.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
You can even get rid of the outer try-catch if you can propagate the exception which probably makes more sense then manually printing the stack trace. If you don't catch some exception in your program you'll get stack trace printed for you automatically.
Also the need to manually close the stream will be addressed in Java 7 with automatic resource management.
With automatic resource management and exception propagation the code reduces to the following:
try (InputStream input = new BufferedInputStream(new FileInputStream(file))) {
// ...
input.read(buffer);
// ...
}
Usually these methods are wrapped up in libraries. Unless you want to write at this level, it is best to create your own helper methods or use existing ones like FileUtils.
String fileAsString = Fileutils.readFileToString(filename);
// OR
for(String line: FileUtils.readLines(filename)) {
// do something with each line.
}
I don't know if it is the right way, but you can have all your code in the same try block, and then have the different catch blocks right after each other.
try {
...
}
catch (SomeException e) {
...
}
catch (OtherException e) {
...
}
If you want to do this in plain Java, the code you have posted looks OK.
You could use 3rd party libraries such as Commons IO, in which you would need to write much less code. e.g.
Check out Commons IO at:
http://commons.apache.org/io/description.html
Sometimes you can reduce the code to the following:
public void foo(String name) throws IOException {
InputStream in = null;
try {
in = new FileInputStream(name);
in.read();
// whatever
} finally {
if(in != null) {
in.close();
}
}
}
Of course this means the caller of foo has to handle the IOException but this should be the case most of the time anyway. In the end you don't really reduce all that much complexity but the code becomes much more readable due to less nested exception handlers.
My take on this without using utilities would be:
InputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
// ...
inputStream.read(buffer);
// ...
} catch (IOException e) {
e.printStackTrace();
throw e; // Rethrow if you cannot handle the exception
} finally {
if (inputStream != null) {
inputStream.close();
}
}
Not a one-liner, but not pretty bad. Using, say, Apache Commons IO it would be:
//...
buffer = FileUtils.readFileToByteArray(file);
//...
The thing to rembember is that standard Java lacks many of these little utilities and easy to use interfaces that everyone needs, so you have to rely on some support libraries like Apache Commons, Google Guava, ... in your projects, (or implement your own utility classes).
Use org.apache.commons.io.FileUtils.readFileToByteArray(File) or something similar from that package. It still throws IOException but it deals with cleaning up for you.
Try the following:
try
{
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[1024];
try
{
// ...
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
//Process the chunk of bytes read
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
inputStream.close();
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Google guava has tried to address this problem by introducing Closeables.
Otherwise you have to wait until AutoCloseable from JDK 7 comes out as it addresses some of the cases when IOException is thrown.