How to properly catch exceptions with java file I/O [duplicate] - java

This question already has answers here:
Closing a Java FileInputStream
(9 answers)
Closed 5 years ago.
I'm trying to become familiar with file I/O in Java. I started off by getting a lot of errors when compiling, such as error: unreported exception IOException; must be caught or declared to be thrown. So I made some changes to the code and ended up with:
public static void main(String[] args){
FileInputStream in = null;
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}catch(IOException e){
}catch(FileNotFoundException e){
}
finally{
if (out != null)
out.close();
}
}
Still, I get this error:
FileIO.java:16: error: exception FileNotFoundException has already been caught
}catch(FileNotFoundException e){
^
FileIO.java:21: error: unreported exception IOException; must be caught or declared to be thrown
out.close();
^
2 errors
Where did I "already catch" FileNotFoundException?
Because of the second error, do I need to put another try and catch statement in the finally clause to catch IOException? That seems messy and over-complicated. Am I doing something else wrong? And why doesn't java let me do what I want without forcing me to catch exceptions?
EDIT:
If I do:
public static void main(String[] args){
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}catch(FileNotFoundException e){
}catch(IOException e){
}
finally{
if (out != null)
out.close();
}
}
I get:
FileIO.java:20: error: unreported exception IOException; must be caught or declared to be thrown
out.close();
^
1 error

Where did I "already catch" FileNotFoundException?
FileNotFoundException extends IOException, which means IOException can catch FileNotFoundException exception. So, there is no point of FileNotFoundException after it.
Just reverse the order, to resolve this issue.
}catch(FileNotFoundException e){
}catch(IOException e){
}
Also, don't leave catch block blank, use them to display appropriate message, else you won't have any clue, if you got any exception.
second error, do I need to put another try and catch statement in the finally clause to catch IOException?
Yes. But, I would suggest to use try-with-resource it will take care of closing resource at the end.
As said, you should use try-with-resource instead
try (FileOutputStream out = new FileOutputStream("people.bin");)
{
out.write(contentBytes);
}
catch(FileNotFoundException e)
{
}catch(IOException e){
}

I am not really sure how the compiler let you the code. Could you please try the below code. I dont have any error when i run it.
Answer to the first question is :
Either remove FileNotFoundException line or put it above IOexception.
Answer to the second question is :
if you think that is messy, you can just duck the exception by using Throws i.e. throws IOException next to main(String[] args).
Java(compiler) pushes you to catch or declare your exceptions(using throws) because, the main purpose of Exceptions in java is not running into errors when the code is run. When an exception happens in the finally block, it leads to error and it ultimately impacts your application at run time. Have to very careful when you are closing stuff in Finally block. If you think, the code looks messy, then you can use Throws key word which solves your concern.
public static void main(String[] args){
FileInputStream in = null;
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}catch(IOException e){
}
finally{
if (out != null){
try{
out.close();
}catch(IOException e){
}
}
}
}

String outputPath = "output.txt";
String content = "hello";
byte[] contentBytes = content.getBytes();
try (FileOutputStream out = new FileOutputStream(outputPath)) {
out.write(contentBytes);
} catch (FileNotFoundException e) {
System.err.println("Failed to find the file to write to: " + outputPath);
} catch (IOException e) {
System.err.println("Failed to write to file: " + outputPath);
}
As QuakeCore mentioned FileNotFoundEception extends IOException, this is why you should catch FileNotFoundEception first.
It is a good practice to print at least some message, so you will not be surprised when there is no output and no exceptions in console / logs.
FileOutputStream implements AutoClosable interface. This why it is better to use try with resources. In this case JVM will close it automatically.

public static void main(String[] args) throws IOException{
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}catch(FileNotFoundException e){
}
finally{
if (out != null)
out.close();
}
}

Since FileNotFoundException extends IOException, then just by catching IOException you are catching all subtypes of IOException.
And regarding your second question, since `.close()` method also throws `IOException`, you can put all the IO code in a method, and have that method to throw `IOException`, then the caller can deal with the any exceptions.
for example:
private static void writeToFile() throws IOException{
FileInputStream in = null;
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}finally{
if (out != null)
out.close();
}
}
and then your main would look like this.
public static void main(String[] args){
FileInputStream in = null;
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
writeToFile();
}catch(IOException e){
}
}
And have a look at tryResourceClose

Related

Exception supposedly never thrown even though it does at runtime

I'm trying to write a small program where I came to the following problem:
In one of my methods I have the following piece of code
try{
rootHuman = Human.load(scanner.next());
}catch(FileNotFoundException f){
//Missing Code
}
where I try to catch a FileNotFoundException. So looking at the function call from Human.load() we have this piece of code
public static Human load(String filename){
try{
Human human;
FileInputStream fileIn = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(fileIn);
human = (Human) in.readObject();
in.close();
fileIn.close();
return human;
}catch(IOException i){
i.printStackTrace();
return null;
}catch(ClassNotFoundException c){
c.printStackTrace();
return null;
}
also when trying to catch the FileNotFoundException here I get the same problem. My Problem is that the compiler tells me that this exception is never thrown, but when I execute the code I can obviously get a FileNotFoundException when the input from scanner.next() is a filename that doesn't exist. I'm kind of pointless here so any piece of advice is very much welcome.
Thanks in advance
Your compiler complains about this:
try{
rootHuman = Human.load(scanner.next());
}catch(FileNotFoundException f){
//Missing Code
}
In your Human.load method you catch a IOException, so a FileNotFoundException (witch is actually a sub-type of IOException) will never be thrown in method "load", this catch clausule will always handle it.
Remove the try catch block when calling Human.load():
rootHuman = Human.load(scanner.next());

Transferring data from input to output File, getting Exception

My data is not getting transferred to the output file , I always get an Exception.
import java.io.*;
import java.util.*;
class TransferData {
public static void main(String[] args) {
String path1="E:\\IO\\Input.txt";
String path2="E:\\IO\\Output.txt";
int data;
System.out.println("Transfering started...");
try {
FileInputStream fis=new FileInputStream(path1);
FileOutputStream fos=new FileOutputStream(path2);
while((data=fis.read())!=-1) {
fos.write(data);
}
}
catch(Exception e) {
System.out.println("exception caught!");
}
System.out.println("Completed...");
}
}
How do I transfer data to output file ?
Tested this code on my local machine it is works without exceptions.
Check is file E:/IO/Input.txt exists.
IS Directory E:/IO is writeable for your user
(If file E:/IO/Output.txt already exists check is it writeable and not opened in another programm)
By code:
It is good practice to close FIS and FOS after programm finished execution.
public class TransferData {
public static void main(String[] args) {
String path1 = "E:\\IO\\Input.txt";
String path2 = "E:\\IO\\Output.txt";
int data;
System.out.println("Transfering started...");
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(path1);
fos = new FileOutputStream(path2);
while ((data = fis.read()) != -1) {
fos.write(data);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("Completed...");
}
}
If you replace System.out.println("exception caught!"); with e.printStackTrace(); then you will get a much more useful error message.
If you then post that error message here, people will be able to help you much more easily.
It could be the case that the program cannot find the file you're trying to read.
I highly suggest to use e.printStackTrace() as the others suggested.
One possible problem might be the filesystem permissions or the file you are trying to read from being not existent.
You might also want to use a "try with resources" to simplify your code.
Your code is missing a close statement for your Streams too.
All together your code would look something like this:
import java.io.*;
import java.util.*;
class TransferData {
public static void main(String[] args) {
String path1="E:\\IO\\Input.txt";
String path2="E:\\IO\\Output.txt";
int data;
System.out.println("Transfering started...");
try (
FileInputStream fis=new FileInputStream(path1);
FileOutputStream fos=new FileOutputStream(path2)
) {
while((data=fis.read())!=-1) {
fos.write(data);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
One last thing, if you post your code on StackOverflow, please do not mix different formatting styles (e.g. { in the same line as an if and sometimes in the next) and try to have the code well formatted from the beginning.
Add e.printStackTrace() to your catch block, and post the data printed in your console here, people will be able to help you better.
The most likely cause of the exception getting thrown is that the system is not able to find the file "E:\\IO\\Input.txt" or "E:\\IO\\Output.txt" make sure that the file's are there and Output.txt is not set to read only.

error unreported exception when use BufferedInputStream

I am trying to copy files using BufferedInputStream, and this error occurred when compile:
BufferedByteStreamCopy2.java:22: error: unreported exception IOException; must be caught or declared to be thrown
bin.close();
^
BufferedByteStreamCopy2.java:24: error: unreported exception IOException; must be caught or declared to be thrown
bout.close();
^
Could you help me to explain this? How can I modify the code? Many thanks!
import java.io.*;
public class BufferedByteStreamCopy2 {
public static void main(String[] args) {
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
try {
FileInputStream fin = new FileInputStream(args[0]);
bin = new BufferedInputStream(fin);
FileOutputStream fout = new FileOutputStream(args[1]);
bout = new BufferedOutputStream(fout);
int c;
while ((c = bin.read()) != -1)
bout.write(c);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Not enough parameter.");
} catch (FileNotFoundException e) {
System.out.println("Could not open the file:" + args[0]);
} catch (Exception e) {
System.out.println("ERROR copying file");
} finally {
if (bin != null)
bin.close();
if (bout != null)
bout.close();
}
}
}
try/catch will catch an Exception but this doesn't apply to an exception thrown in a finally block. You need a try catch for the close() in there as well.
Note: copying a byte at a time is pretty inefficient, I assume this is just an exercise. As #EJP point out there is more read() and write() methods.

Preferred way to clean-up resources in Java 1.6

I regularly see this style of resource clean-up:
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} finally {
if (in != null) {
in.close();
}
}
I have always used the following style:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
But am I missing something? Is there an advantage to the former that I'm not seeing?
I suspect its to avoid having two nested try/catch blocks instead of one.
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} catch(IOException ioe) {
// handle exception.
} finally {
IOUtils.closeQuietly(in);
}
The second case is incomplete.
try {
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
} catch(IOException e) {
// handle exception
}
If you have multiple files, this could get really messy.
Suppose that in the first example you have some other code before defining in that gets you out of the try block. If you get to the finally without in been defined you will get a NullPointerException when trying to close it. So you will have to make the check to avoid errors like that.
This is very simple example, And may not create a problem as you are creating InputStream in same bloke. But if InputStream is closed because of some Exception or other fault, in that case your code will fail, So its always better to check if InputStream is available
The second one will not compile since the constructor of FileInputStream can throw a FileNotFoundException, thus you'd need an extra try-catch block, unless of course, the method itself throws it.
Another common idiom is to write a closeQuietly() method to avoid having to write the if (is != null) check all over your finally blocks. This is what Apache Common's IOUtils does:
public static void closeQuietly(InputStream input) {
try {
if (input != null) {
input.close();
}
} catch (IOException ioe) {
// ignore
}
}
Also note that since Java 7, you can use the following:
try (InputStream is = new FileInputStream(file)) {
} catch (final FileNotFoundException | IOException ex) {
}
The null check here for the InputStream is necessary as it is possible that the variable might not be assigned. In this case a NullPointerException would be thrown when attempting to close it when calling:
in.close();
In the 2nd block outside of the try/catch block:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
You can easily encounter other exceptions before entering the block and the InputStream is never closed.
Lets say you need to open not one, but two files. You would do
final InputStream in = new FileInputStream(file1);
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
in.close();
}
If the out fails to open, you will get an exception and because it's out of the try block in won't be closed in the finally block.
In the other method:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
if (out != null) out.close();
if (in != null) in.close();
}
If out fails to open, you will go to the finally block and close both streams. If in fails to open, you will go to the finally block, and free only in - because out==null.
edit
As the aetheria mentioned, that code wouldn't work because close() throws exception in Java. It can easily be fixed by putting each resource release in it's own try-catch block:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
try{ out.close(); }catch(Exception e){}
try{ in.close(); }catch(Exception e){}
}
I ditched the null checking - if in or out is null, it'll throw a NullPointerException that will be ignored. And the reason I ignore close exceptions is that disposal methods shouldn't throw exceptions in the first place. If handling closing exceptions is required, you can always close the streams again, after the finally block. That way, any stream that can be closed will be closed already(so you wouldn't have to worry about it), and you can handle any exceptions from close more elegantly.
Now, aetheria also suggested to put a separate try-finally block for each resource that would look like this:
final InputStream in = new FileInputStream(file1);
try {
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
}
} finally {
in.close();
}
This works, but even with only two resources, it's much less elegant, as it splits the allocations and releasing code, making it harder to keep track of it(in my opinion, at least).

Do I have to close FileOutputStream which is wrapped by PrintStream?

I'm using FileOutputStream with PrintStream like this:
class PrintStreamDemo {
public static void main(String args[]) {
FileOutputStream out;
PrintStream ps; // declare a print stream object
try {
// Create a new file output stream
out = new FileOutputStream("myfile.txt");
// Connect print stream to the output stream
ps = new PrintStream(out);
ps.println ("This data is written to a file:");
System.err.println ("Write successfully");
ps.close();
}
catch (Exception e) {
System.err.println ("Error in writing to file");
}
}
}
I'm closing only the PrintStream. Do I need to also close the FileOutputStream (out.close();)?
No, you only need to close the outermost stream. It will delegate all the way to the wrapped streams.
However, your code contains one conceptual failure, the close should happen in finally, otherwise it's never closed when the code throws an exception between opening and closing.
E.g.
public static void main(String args[]) throws IOException {
PrintStream ps = null;
try {
ps = new PrintStream(new FileOutputStream("myfile.txt"));
ps.println("This data is written to a file:");
System.out.println("Write successfully");
} catch (IOException e) {
System.err.println("Error in writing to file");
throw e;
} finally {
if (ps != null) ps.close();
}
}
(note that I changed the code to throw the exception so that you understand the reason of the problem, the exception namely contains detailed information about the cause of the problem)
Or, when you're already on Java 7, then you can also make use of ARM (Automatic Resource Management; also known as try-with-resources) so that you don't need to close anything yourself:
public static void main(String args[]) throws IOException {
try (PrintStream ps = new PrintStream(new FileOutputStream("myfile.txt"))) {
ps.println("This data is written to a file:");
System.out.println("Write successfully");
} catch (IOException e) {
System.err.println("Error in writing to file");
throw e;
}
}
No , here is implementation of PrintStream's close() method:
public void close() {
synchronized (this) {
if (! closing) {
closing = true;
try {
textOut.close();
out.close();
}
catch (IOException x) {
trouble = true;
}
textOut = null;
charOut = null;
out = null;
}
}
You can see out.close(); which closes output stream.
No you dont need to. PrintStream.close method automatically closes the underlining output stream.
Check the API.
http://download.oracle.com/javase/6/docs/api/java/io/PrintStream.html#close%28%29
No, according to the javadoc, the close method will close the underlying stream for you.
No. It is not require to close other components. when you close stream it automatically close other related component.

Categories