Java File Exception Handling - java

I am supposed to create a sample program for exception handling for file operations for my java assignment. I am having trouble understanding since I am a C++ guy. It would be really very helpful if somebody could point out the flaw in my code below. I am referring this article. Eclipse is giving me "Unreachable catch block for FileNotFoundException. This exception is never thrown from the try statement body" error.
import java.io.*;
public class file {
public static void main(String[] args) {
String arg1 = args[0];
String arg2 = args[1];
System.out.println(arg1);
System.out.println(arg2);
File f1, f2;
try {
f2 = new File(arg2);
f1 = new File(arg1);
}
catch(FileNotFoundException e) {
/*
if(!f1.exists()) {
System.out.println(arg1 + " does not exist!");
System.exit(0);
}
if(!f2.exists()) {
System.out.println(arg2 + " does not exist!");
System.exit(0);
}
if(f1.isDirectory()) {
System.out.println(arg1 + " is a Directory!");
System.exit(0);
}
if(f2.isDirectory()) {
System.out.println(arg2 + " is a Directory!");
System.exit(0);
}
if(!f1.canRead()) {
System.out.println(arg1 + " is not readable!");
System.exit(0);
}
if(!f2.canRead()) {
System.out.println(arg2 + " is not readable!");
System.exit(0);
}*/
}
}
}

Look at the docs for the File constructor you're calling. The only exception it's declared to throw is NullPointerException. Therefore it can't throw FileNotFoundException, which is why you're getting the error. You can't try to catch a checked exception which the compiler can prove is never thrown within the corresponding try block.
Creating a File object doesn't check for its existence. If you were opening the file (e.g. with new FileInputStream(...) then that could throw FileNotFoundException... but not just creating a File object.

This is because the constructor of class File with one argument
public File(String pathname)
Parameters:pathname - A pathname string Throws: NullPointerException - If the pathname argument is null
Throws: NullPointerException - If the pathname argument is null
throws only one exception and that is NullPointerException. Your code tries to catch a FileNotFoundException which is not related to NullPointerException and this is why you get this error in Eclipse.
One way to go is to catch exceptions of class Exception which is the super class of all exceptions in Java. Another way is to catch all the exceptions (each in different catch block) that the invoked construct throws (which can be easily obtained by going through its API). The third approach is to catch only the exceptions (again which are actually thrown by the construct) that make sense to your application and ignore the others.

Related

Check if an exception was thrown and continue after the exception was thrown

I want to make a test that reads from a file some data and passes that data to a function. That function calls other methods and some of them throw some exceptions. I'm interested in how can I check whether or not calling the method with the parameters from the file triggered an IOException somewhere along. I know that the code snippet provided will stop the execution because I've used assert. How should I write if I want to check if an IOException was thrown and if it was, to get the error message, without stopping the execution of the test? Thanks!
void test() throws IOException {
Service service = helperFunction();
File articles = new File("file.txt");
Scanner scanner = new Scanner(articles);
while(scanner.hasNextLine()) {
String line = scanner.nextLine();
line = line.replaceAll("[^\\d]", " ");
line = line.trim();
line = line.replaceAll(" +", " ");
String[] numberOnTheLine = line.split(" ");
List<Integer> list = Arrays.stream(numberOnTheLine).map(Integer::valueOf).collect(Collectors.toList());
Article article = new Article(Long.valueOf(list.get(0)),
new HashSet<>(List.of(new Version(list.get(1)))));
List<List<Article>> listOfArticles = Collections.singletonList(List.of(article));
Assertions.assertThrows(IOException.class,
() -> service.etlArticles(listOfArticles.stream().flatMap(List::stream).collect(Collectors.toList())));
}
}
Simple; a try/catch statement will take care of it.
Replace this:
service.etlArticles(listOfArticles.stream().flatMap(List::stream).collect(Collectors.toList())));
With:
try {
service.etlArticles(listOfArticles.stream().flatMap(List::stream).collect(Collectors.toList())));
} catch (IOException e) {
// Code jumps to here if an IOException occurs during the execution of anything in the try block
}
You are free to e.g. do some logging and then just Assert.fail, if you want.
assertThrows is quite simple, all it does is this:
try {
runThatCode();
} catch (Throwable e) {
if (e instanceof TypeThatShouldBeThrown) {
// Great, that means the code is working as designed, so, just...
return;
}
// If we get here, an exception was thrown, but it wasn't the right type.
// Let's just throw it, the test framework will register it as a fail.
throw e;
}
// If we get here, the exception was NOT thrown, and that's bad, so..
Assert.fail("Expected exception " + expected + " but didn't see it.");
}
Now that you know how it works, you can write it yourself and thus add or change or log or whatever you want to do during this process at the right place. However given you know it's IOException, instead of an instanceof check you can just catch (IOException e), simpler.

Type of Exception in catch block

I am learning how to create file and directory in java using this code.
On the ERROR LINE I am getting error as "IOException is never thrown in this block".
So how do I know which function is throwing what type of Exception?
Or if I am not sure I should use generic Exception in every catch block.
public class FileTest {
public static void main(String[] args) {
//file creation
boolean flag = false;
File file = new File("/IdeaProjects/JavaCode/jstest.txt");
try {
flag = file.createNewFile();
}catch (IOException e){
e.printStackTrace();
}
System.out.println("file path is : " + file.getPath());
//dir creation
boolean dirFlag = false;
File fileDir = new File("/IdeaProjects/JavaCode/js");
try{
dirFlag = fileDir.mkdir();
}catch (IOException e){//ERROR LINE
e.printStackTrace();
}
if(dirFlag)
System.out.println("created");
else
System.out.println("exist");
}
}
The java.io.File#mkdir method only declares to throw SecurityException - see API.
java.lang.SecurityException is a RuntimeException and doesn't require being caught, although you may want to, depending on the context (again, see API).
Catching general java.lang.Exception in every catch block is absolutely not a recommended practice, although you may sometimes have to (not in your present case though).
See here for some SO literature on the matter.
Remember what methods throw exceptions and which exceptions they are.
Check the documentation if you think a method may throw an exception.
Just attempt to compile the code and fix the errors the compiler throws (They will tell you what exceptions are thrown by what method if the try-catch block is missing).
The method in question (File.mkdir()) throws a SecurityException which doesn't need to be caught (you can if need be) as it is an unchecked RuntimeException.
java.io.File: https://docs.oracle.com/javase/7/docs/api/java/io/File.html#mkdir()
SecurityException: https://docs.oracle.com/javase/7/docs/api/java/lang/SecurityException.html
Quoting JLS Section 11.2:
It is a compile-time error if a catch clause can catch checked exception class E1 and it is not the case that the try block corresponding to the catch clause can throw a checked exception class that is a subclass or superclass of E1, unless E1 is Exception or a superclass of Exception.
If no method you invoke in the try block declares that it throws IOException (and you don't throw new IOException(..) directly either), it is a compile-time error if you try to catch an IOException.

Catching thrown exceptions with an Exception class I created

In GraphicsFileNotFoundException.java all I have is an import of FileNotFoundException and the class GraphicsFileNotFoundException which extends FileNotFoundException.
In my main java file, I'm trying to read in a graphics file with the method getGraphicsFile which throws GraphicsFileNotFoundException.
My brain is pooped after a good 40 minutes trying to find out how to catch this exception. I've tried using a try-catch block and catching GraphicsFileNotFoundException but I still get the error
unreported exception GraphicsFileNotFoundException ; must be caught
or declared to be thrown.
public void getGraphicsFile(String fileName) throws GraphicsFileNotFoundException {
String graphics = "";
Scanner getGraphics = null;
try {
getGraphics = new Scanner(new File(fileName));
}
catch (GraphicsFileNotFoundException e){
System.out.println("Error! File can't be found :/");
}
You need to either properly extend the FileNotFoundException class or manually throw an exception inside your try block.
Assuming this is for an assignment (I'm not sure why else you'd need to specifically extend this exception) you'll need to take another look at your GraphicsFileNotFoundException class and make sure that it does what it needs to.
To throw an exception, simply write your condition and the throw statement:
if(needToThrow) {
throw new GraphicsFileNotFoundException();
}
To catch an exception, surround the throw statement with a try block immediately followed by a catch block.
try {
// code here
if(needToThrow) {
throw new GraphicsFileNotFoundException();
}
}
catch(GraphicsFileNotFoundException e) {
// handle the error (print stack trace or error message for example)
e.printStackTrace(); // this is printing the stack trace
}
I recommend using Eclipse if you aren't already because many times it will offer to surround throw statements that need to be caught with a automatically generated try catch block.

In Java, how to force an Exception to "bubble up"?

I have a method that throws an Exception, which calls a method which throws an Exception, etc etc. So several methods that "throw Exception" are daisy-chained.
The first method that calls the submethod, puts that submethod in a try-catch block that catches any Exception that gets thrown inside that call. IN THEORY. In practice, no Exception is being caught by that try-catch block. Is there a way to remedy that?
Here is the code:
try {
CSVSingleton.tryToReadBothFiles(FILE1_PATH, FILE2_PATH);
} catch (Exception e) { // THIS BLOCK NEVER GETS ENTERED BY THE PATH O EXECUTION
System.out.println("There was an exception reading from at least one of the files. Exiting.");
System.exit(0);
}
here is the method from the CSVSingleton class:
public static void tryToReadBothFiles(String filePath1, String filePath2) throws Exception {
file1 = new CSVFileForDwellTime1(filePath1);
file2 = new CSVFileForDwellTime2(filePath2);
}
And here is code from the CSVFileForDwellTime1 class:
public CSVFileForDwellTime1(String filePath) throws Exception {
super(filePath);
}
and then here is the code that actually throws an original FileNotFoundException:
public GenericCSVFile(String filePath) throws Exception{
this.filePath = filePath;
try {
fileReader = new FileReader(filePath);
csvReader = new CSVReader(
fileReader);
header = getActualHeaderNames();
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// e.printStackTrace();
}
}
My guess is that the FileNotFoundException in the last method is caught by the catch block and so doesn't "bubble up". But is there a way to force it to bubble up?
Immediate answer:
Your thought is exactly right,
try {
fileReader = new FileReader(filePath);
csvReader = new CSVReader(
fileReader);
header = getActualHeaderNames();
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// e.printStackTrace();
}
This suppresses the exception
Either remove the try-catch block (desired unless you can actually do something with the exception)or re-throw it within the catch block.
Explanation
Generally with checked exceptions like this you have 2 options
Catch the exception and do something to remedy the exception
Throw the exception to the caller
What you have done here falls into the 1st category except that you have not done anything useful in the catch block (printing to console is rarely useful in this case because the exception message itself normally has enough information to see what has gone wrong)
The 2nd category is achieved either by not using a try-catch block and thus adding throws FileNotFoundException to the method signature. Alternatively explicitly throw the exception that you caught using:
catch(FileNotFoundException e)
{
//do something
throw e;
}
however in this case if do something isn't worthwhile you have unnecessarily caught something just to throw it on.
You can think of it like this:
Alice throws a ball to Charlie
Bob intercepts the ball
Bob then looks at the ball and then throws it to Charlie
Bonus Points
When you know the exception that could occur make sure to actually catch or throw that exception and not a parent of that exception.
Take the following method signatures for example:
public String method1() throws Exception
public String method2() throws FileNotFoundException
Here method2 clearly tells the caller what could happen and can help then figure out why the exception is being called (without having to read through the code or experience the error).
Secondly other exceptions can occur and you are potentially catching the wrong exception, take the following example:
try{
fileReader = new FileReader(filePath); //could potentially throw FileNotFoundException
fileReader = null; //woops
csvReader = new CSVReader(fileReader); //throws NullPointerException but the compiler will not know this
//....other stuff....//
}
catch(Exception e){
// the compiler told me that a FileNotFoundException can occur so i assume that is the reason the catch has executed
System.err.println("You have entered an invalid filename");
//doing anything here that would fix a FileNotFoundException is pointless because that is not the exception that occured
}
Use a throw in the catch clause.
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// Continue up, Mr. Exception!
throw e;
}
Alternatively, wrap the exception as appropriate (since an IOException is checked this handy here) - this is called a Chained Exception. Then, depending on what is thrown, the throws Exception can be removed from the method signature.
throw new RuntimeException("Could not read file: " + filePath, e);
If you don't want to catch it, then don't. Alternatively, you can just throw it again with a throw-statement. You can also throw a new Exception of any class you like. You should only catch an Exception at a level where you can react to it properly. As you found out, catching it at that low level is not helpful, so do not catch it there.
You can rethrow the exception once you catch it, for callees further up the stack to handle. You can change what exception it is too if a new type of exception makes more sense at a higher level.
catch (SomeSpecificException e)
{
some code here
throw new AMoreBroadException("I really need the callee to handle this too");
}
Technically you just need to add throw e right after System.out.println("Could not read file with name: " + filePath); and the exception will propagate up to the first method.
However, this would not be a clean way to handle the exception, because in this case all you'd be doing is printing an error message at the cost of changing the location of the original FileNotFoundException. Ideally, when you need to inspect an exception stacktrace, you expect a line of code throwing an exception to be the actual line that really caused the exception.
The throws Exception in the method declaration should be considered part of the contract of the method, i.e. it describes a possible behavior of the method. You should always ask yourself: Does it make sense for a FileNotFoundException to be specified as a possible exceptional behavior for the method/constructor I'm writing? In other words, do I want to make the caller of my method aware of this exception and leave it to the caller to deal with it? If the answer is yes (and in this case I would say it makes sense), then avoid wrapping the code in a try-catch block. If no, then your catch block should be responsible for dealing with the exception itself. In this specific example IMO there is not much you can do in the catch statement, so just remove the try-catch.
As mentioned by others, you should declare the most specific exception in the method signature (throws FileNotFoundException instead of throws Exception).

Java exception handling method

I'm having a little bit of trouble implementing the following method while handling the 3 exceptions I'm supposed to take care of. Should I include the try/catch blocks like I'm doing or is that to be left for the application instead of the class design?
The method says I'm supposed to implement this:
public Catalog loadCatalog(String filename)
throws FileNotFoundException, IOException, DataFormatException
This method loads the info from the archive specified in a catalog of products and returns the catalog.
It starts by opening the file for reading. Then it proceeds to read and process each line of the file.
The method String.startsWith is used to determine the type of line:
If the type of line is "Product", the method readProduct is called.
If the type of line is "Coffee", the method readCoffee is called.
If the type of line is "Brewer", the method readCoffeeBrewer is called.
After the line is processed, loadCatalog adds the product (product, coffee or brewer) to the catalog of products.
When all the lines of the file have been processed, loadCatalog returns the Catalog of products to the method that makes the call.
This method can throw the following exceptions:
FileNotFoundException — if the files specified does not exist.
IOException — If there is an error reading the info of the specified file.
DataFormatException — if a line has errors(the exception must include the line that has the wrong data)
Here is what I have so far:
public Catalog loadCatalog(String filename)
throws FileNotFoundException, IOException, DataFormatException{
String line = "";
try {
BufferedReader stdIn = new BufferedReader(new FileReader("catalog.dat"));
try {
BufferedReader input = new BufferedReader(
new FileReader(stdIn.readLine()));
while(! stdIn.ready()){
line = input.readLine();
if(line.startsWith("Product")){
try {
readProduct(line);
} catch(DataFormatException d){
d.getMessage();
}
} else if(line.startsWith("Coffee")){
try {
readCoffee(line);
} catch(DataFormatException d){
d.getMessage();
}
} else if(line.startsWith("Brewer")){
try {
readCoffeeBrewer(line);
} catch(DataFormatException d){
d.getMessage();
}
}
}
} catch (IOException io){
io.getMessage();
}
}catch (FileNotFoundException f) {
System.out.println(f.getMessage());
}
return null;
}
It depends on whether you want the class or another portion of the application that is using it to handle the exception and do whatever is required.
Since the code that will use the loadCatalog() probably won't know what to do with a file I/O or format exception, personally, I'd go with creating an exception like CatalogLoadException and throw it from within the loadCatalog() method, and put the cause exception (FileNotFoundException, IOException, DataFormatException) inside it while including an informative message depending on which exception was triggered.
try {
...
//do this for exceptions you are interested in.
} catch(Exception e) {
//maybe do some clean-up here.
throw new CatalogLoadException(e); // e is the cause.
}
This way your loadCatalog() method will only throw one single and meaningful exception.
Now the code that will use loadCatalog() will only have to deal with one exception: CatalogLoadException.
loadCatalog(String filename) throws CatalogLoadException
This also allows your method to hide its implementation details so you do not have to change its "exception throwing" signature when the underlying low level structure changes. Note that if you change this signature, every piece of code would need to change accordingly to deal with the new types of exceptions you have introduced.
See also this question on Exception Translation.
Update on the throwing signature requirement:
If you have to keep that signature then you don't really have a choice but to throw them to the application and not catch them inside the loadCatalog() method, otherwise the throws signature would be sort of useless, since we aren't going to throw the exact same exception that we have just dealt with.
The general idea is that you percolate exceptions up to the appropriate place to handle them. I am going to guess that your instructor expects them to be handled in main. In this case I can guess that because of the throws clause you were given. A simple rule of thumb is that if the method declares the exception in the throws clause you do not catch it in that method. So the method you are writing should have no catch statements.
To do that you would change your code something like:
public Catalog loadCatalog(String filename)
throws FileNotFoundException,
IOException,
DataFormatException
{
String line = "";
BufferedReader stdIn = new BufferedReader(new FileReader("catalog.dat"));
BufferedReader input = new BufferedReader(new FileReader(stdIn.readLine()));
while(!stdIn.ready())
{
line = input.readLine();
if(line.startsWith("Product"))
{
readProduct(line);
}
else if(line.startsWith("Coffee"))
{
readCoffee(line);
}
else if(line.startsWith("Brewer"))
{
readCoffeeBrewer(line);
}
}
return null;
}
and then in the method (presumably main) that calls loadCatalog you would have:
try
{
loadCatalog(...);
}
catch(FileNotFoundException ex)
{
ex.printStackTrace();
}
catch(IOException ex)
{
ex.printStackTrace();
}
catch(DataFormatException ex)
{
ex.printStackTrace();
}
replacing the printStackTrace with something appropriate.
That way the method, loadCatalog, doesn't deal with displaying the error messages, so you can call the method in GUI or console code and the code that calls it can choose how to display the error to the user (or deal with it in some way).
Here is an excellent article of Heinz Kabutz, dealing with exception handling.
http://www.javaspecialists.eu/archive/Issue162.html

Categories

Resources