how to get the filename of a thrown IOException in java? - java

I have a try block which handles quite a few file opening/closing/reading/writing (more than one file).
It looks like:
try {
// commands
}
catch (IOException e) {
System.err.println("Error: " + e);
}
The main problem is that e.toString() does not contain information about the filename for which the exception was thrown, if there is an error.
I could check each read/write/open/close operation separately, and then know which file the error happens with, but that seems to defeat the purpose of having the elegant try-catch structure.
Is there any other way out? I just want to be able to print the file name for which e had the error in the try block.
EDIT: Maybe I should make it clear in which scenario this issue arises. This happens when I parse command-line arguments, input/output files, etc. I pass the file names to various functions and methods that can return with an IO error. It seems reasonable to require that I would have a generic way of handling any file problem by printing the error and the filename that had that error. I understand that IOException is more broad than handling IO with files, but surely it makes sense, given that IOException is a specialized exception class, to have a method that returns the IO source for which the error occurred.

You don't - as you know, IOException doesn't have information about the File that generated the exception. It's purpose it too general. If you roll your own, you can capture relevant information and catch your own exception instead.
In the various methods that handle your input, wrap the relevant section in try/catch blocks, catch the IOException, and throw your own with the additional data.
Here is a complete program that demonstrates the basic idea.
class FooException extends Exception {
private static final long serialVersionUID = 2816777468035627105L;
private final String filename;
private final Throwable cause;
public FooException(String filename) {
this(filename, null);
}
public FooException(String filename, Throwable cause) {
this.filename = filename;
this.cause = cause;
}
#Override
public String getMessage() {
return "Error reading file";
}
#Override
public Throwable getCause() {
return cause;
}
public String getFilename() {
return filename;
}
}
public class Soj25375647 {
public static void main(String[] args) {
try {
throwsAnException();
// Do other things that might throw my exception
} catch (FooException e) {
System.err.printf("File: %s, error: %s, caused by %s%n", e.getFilename(), e, e.getCause());
}
}
public static void throwsAnException() throws FooException {
try {
int x = 2 / 0;
} catch (ArithmeticException e) {
throw new FooException("bob.file", e);
}
}
}
Output
File: bob.file, error: soj25375647.FooException: Error reading file, caused by java.lang.ArithmeticException: / by zero
See Also Exception-Handling Antipatterns.

I think I see what's happening here. You probably have something like this:
try {
for (int i = 0; i < something; i++) {
File f = getSomeFile(i);
// Operations that might throw an IOException
}
}
catch (IOException e) {
// handle
}
This is not a good idea; as you say you don't know the file that caused the error. Instead try something like this:
for (int i = 0; i < something; i++) {
File f = getSomeFile(i);
try {
// Operations that might throw an IOException
}
catch (IOException e) {
// handle
break;
}
}
This way, you still have f around when the error is thrown, but it also breaks out of the loop on an error just like the original code. Hope this helps!

Related

File Scanner: Unreported exception FileNotFoundException; must be caught or declared to be thrown

I have tried everything I can find on the internet, and nothing seems to fix this. I am begging for help, tell me what I am doing wrong. I am brand new to Java. Thanks!
import java.util.Scanner;
class File_Scanner {
public static void read() {
File credentials_file = new File("credentials.txt");
Scanner file_reader = new Scanner(credentials_file);
String[] users = new String[6];
int index_counter = 0;
try {
while (file_reader.hasNextLine()) {
users[index_counter] = file_reader.nextLine();
}
file_reader.close();
} catch (Exception e) {
System.out.println(e.getClass());
}
}
}
This is showing the following error
Unreported exception FileNotFoundException; must be caught or declared to be thrown
I would like to recommend to surround the whole read function with a try/catch block like the following.
import java.util.Scanner;
class File_Scanner{
public static void read(){
try {
File credentials_file = new File("credentials.txt");
Scanner file_reader = new Scanner(credentials_file);
String[] users = new String[6];
int index_counter = 0;
while (file_reader.hasNextLine()) {
users[index_counter] = file_reader.nextLine();
}
file_reader.close();
} catch (Exception e) {
System.out.println(e.getClass());
}
}
}
The idea of try/catch is to avoid any error that might occur while running your program. In your case, Scanner file_reader = new Scanner(credentials_file); can throw an error if the credentials_file is not found or deleted. Hence you need to cover this around a try block which will give you an exception which can be handled to show proper response message in the catch block.
Hope that helps!
I agree with the other answers as to the problem (the Scanner can throw an exception if it can't find the file). I haven't seen what I'd consider the correct solution though.
String[] users = new String[6];
int index_counter = 0;
File credentials_file = new File("credentials.txt");
try (Scanner file_reader = new Scanner(credentials_file)) {
while (file_reader.hasNextLine()) {
users[index_counter] = file_reader.nextLine();
index_counter++;
}
} catch (FileNotFoundException e) {
// handle exception
} catch (NoSuchElementException e) {
// handle exception
} catch (IllegalStateException e) {
// handle exception
}
The try-with-resources statement will automatically close the Scanner for you. This will work with any class that implements the AutoCloseable interface.
And in this case, it puts the statement within the scope of the try, so exceptions will be caught.
Your exception handling is questionable, so I didn't include it. But that's not really the point here. You can read more about Best Practices to Handle Exceptions in Java or How to Specify and Handle Exceptions in Java.
There is an argument that you should let the exception bubble up to the caller. This answer describes how to do that. But in this case, the caller doesn't really know how to handle a FileNotFoundException, because it doesn't know anything about the file. The file is defined in this method.
You could throw a different, more explanatory exception. Or you could handle the exception here by explaining what a credentials.txt is. Or fail over to a default. Or just log the exception, although that's questionable. If you do that, you should explain (in a comment) why that is sufficient.
I added a line to increment index_counter just because it seemed to be missing.
See also
Why do I get "Exception; must be caught or declared to be thrown" when I try to compile my Java code?
Am I using the Java 7 try-with-resources correctly?
Java has checked exceptions. Which means that if the code within your method declares that it might possibly throw a particular exception, your method either needs to do one of the following:
Either (1) handle that exception:
public static void read() {
try {
// your method code
} catch (FileNotFoundException ex) {
// handle the exception
}
}
Or (2) declare that it might possibly throw that exception:
public static void read() throws FileNotFoundException {
// your method code
}
Just add this to your method declaration:
public static void read() throws FileNotFoundException
For ways to handle checked exceptions in java check this(Oracle Docs Java Tutorials):
You associate exception handlers with a try block by providing one or
more catch blocks directly after the try block. No code can be between
the end of the try block and the beginning of the first catch block.
try {
} catch (ExceptionType name) {
} catch (ExceptionType name) {
}
And this:
Sometimes, it's
appropriate for code to catch exceptions that can occur within it. In
other cases, however, it's better to let a method further up the call
stack handle the exception
public void writeList() throws IOException {
P.S. Also, it has been already discussed on stackoverflow, so maybe should be marked as duplicate.
You should read the java checked exception
public static void read() {
try {
File credentials_file = new File("credentials.txt");
Scanner file_reader;
file_reader = new Scanner(credentials_file);
String[] users = new String[6];
int index_counter = 0;
while (file_reader.hasNextLine()) {
users[index_counter] = file_reader.nextLine();
}
file_reader.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (Exception e) {
System.out.println(e.getClass());
}
}

Handle Exception after all lines have been finished execution without finally

I need methodA2 also gets executed even though there is an exception by methodA1(). Here I have added only two methods as methodA1() and methodA2(). Let's say there are many methods. In that case also, the solution should be able to applicable.
class A {
String methodA1() throws ExceptionE {
// do something
}
String methodA2() throws ExceptionE {
// do something
}
}
class C extends A {
String methodC() throws ExceptionE2 {
try {
methodA1();
methodA2();
} catch (ExceptionE e) {
throw new ExceptionE2();
}
}
}
Please note that there can be many methods invoked with methodA1, methodA2. In that case having multiple try, catch, finally will look ugly.. So are there any other methods to do that?
I need to store error information in a log file. In methodA1(), methodA2() ... information in each tag is get validated. what I want is having all the error information in log file. Once exception throws it will generate log file. So I will miss validation information from other tags. So we can't go for finally approach.
You can use a loop with Java 8 lambdas:
interface RunnableE {
void run() throws Exception;
}
class Example {
public static void main(String[] args) {
List<RunnableE> methods = Arrays.asList(
() -> methodA1(),
() -> methodA2(),
() -> methodA3()
);
for (RunnableE method : methods) {
try {
method.run();
} catch (Exception e) {
// log the exception
}
}
}
private static void methodA1() throws Exception {
System.out.println("A1");
}
private static void methodA2() throws Exception {
System.out.println("A2");
}
private static void methodA3() throws Exception {
System.out.println("A3");
}
}
Please note that the interface is needed only when methods throw checked exception. If they were throwing only runtime exceptions, you could use java.lang.Runnable instead.
No other way. If each method can throw exception, but you want to continue execution of remaining methods anyway, then each method call must be in its own try-catch block.
Example:
List<Exception> exceptions = new ArrayList<>();
try {
methodA1();
} catch (Exception e) {
exceptions.add(e);
}
try {
methodA2();
} catch (Exception e) {
exceptions.add(e);
}
try {
methodA3();
} catch (Exception e) {
exceptions.add(e);
}
if (! exceptions.isEmpty()) {
if (exceptions.size() == 1)
throw exceptions.get(0);
throw new CompoundException(exceptions);
}
You will of course have to implement the CompoundException yourself.

Exception to cause EOL with streamtokenizer?

I am writing a small calculator that goes through the input in token form by using streamtokenizer. However, when catching an exception I want it to either ignore all other exceptions, or move to the EOL. I can't just break as the progream isn't meant to crash, just ignore all succeeding exceptions for that input.
So either I try to set up exceptions to ignore every exception following the first, or I try to get streamtokenizer to move to EOL after catching an exception.
Either way I have no idea to get any of the two options functional.
public static void main(String[] args) throws customException {
Calculator casio = new Calculator(new Stokenizer());
while (true) {
try {
casio.statement();
}
} catch (customException error) {
System.out.println(syntaxError.getMessage());
}
}
}
Stream tokenizer docs is found at http://docs.oracle.com/javase/7/docs/api/java/io/StreamTokenizer.html
You could try something like that to go to the end of line:
public void statement() throws IOException {
int tt = StreamTokenizer.TT_EOF;
try {
while((tt = tokenizer.nextToken()) != StreamTokenizer.TT_EOF) {
// ...
}
} catch (CustomException syntaxError) {
System.out.println(syntaxError.getMessage());
gotoEOL();
}
}
private void gotoEOL() {
try {
while(tokenizer.nextToken() != StreamTokenizer.TT_EOL)
;
} catch (IOException e) {
e.printStackTrace();
}
}
Using A4Ls answer I made a little function and added it before every throw. Probably not the best solution, but it works.
private void gotoEOL() {
while (!tokenizer.isEOL()) {
tokenizer.nextToken();
// System.out.println(tokenizer.getToken());
}

I am trying to create a file via a button press but i keep running into an error

I am creating a checkbook and am unable to create a file to write to for each separate account. When I try to create the file I get the error "unreported exception IOException; must be caught or declared to be thrown". I try to declare that my action listener method throws an exception but that makes the action listener method no longer able to work. I then tried to create a separate method that creates the file and is called by the button press but i still run into the same error
Here is my code:
public void actionPerformed(ActionEvent e) {
...
if (e.getSource() == create) {
creatNewAccount(name3.getText());
BALANCE = Double.parseDouble(name2.getText());
}
}
public void creatNewAccount(String s) throws IOException {
FileWriter fw = new FileWriter(s + ".txt", false);
}
creatNewAccount is declared as possibly throwing an IOException. IOException is not a RuntimeException, so you must catch it.
if (e.getSource() == create) {
try {
creatNewAccount(name3.getText());
} catch (IOException ie) {
ie.printStackTrace();
// handle error
}
BALANCE = Double.parseDouble(name2.getText());
}
For more information, please read about The Catch or Specify Requirement and Catching and Handling Exceptions.
A few other things I noticed:
- The word you're looking for is create, not creat.
- You're assigning something to BALANCE. Uppercase names are generally reserved for constants. Consider renaming this variable balance.
- Consider more descriptive names for your text fields. name2 and name3 don't really say much.
IOException is a checked exception. Given that you're calling it within an ActionListener, rethrowing the exception is not an option so you need to catch it.
try {
creatNewAccount(name3.getText());
} catch (IOException e) {
e.printStackTrace();
// more exception handling
}
In your actionPerformed() you need to put a try/catch block around the createNewAccount call. What you do with the exception once caught is up to you -- an easy thing to do is to wrap it in a RuntimeException which does not need to be caught (but might foul up your process until you do something more elaborate).
public void actionPerformed(ActionEvent e) {
...
if (e.getSource() == create) {
try {
creatNewAccount(name3.getText());
} catch( IOException ioe) {
System.err.println("Whoops! " + ioe.getMessage());
throw new RuntimeException("Unexpected exception", ioe);
}
BALANCE = Double.parseDouble(name2.getText());
}
}
It's likely you'll just need to catch the exception inside the method:
public void creatNewAccount(String s) {
try{
FileWriter fw = new FileWriter(s + ".txt", false);
} catch (IOException e){
//TODO something to handle the error
}
}

exception.getMessage() output with class name

I'm trying to fix an issue, in my application I have this code
try {
object1.method1();
} catch(Exception ex) {
JOptionPane.showMessageDialog(nulll, "Error: "+ex.getMessage());
}
and the object1 would do something like that:
public void method1() {
//some code...
throw new RuntimeException("Cannot move file");
}
I get a messsage in my option pane like this:
Error: java.lang.RuntimeException: Cannot move file
but I used getMessage and not toString method, so the name of the class shouldn´t appear, right?
What I am doing wrong?
I already tryied with a lot of exceptions, even Exception itself. I'm looking to solve this no without the need to implement my own Exception subclass
PROBLEM SOLVED - thank you all!
The try and catch were actually being called in get() method from SwingWorker which constructs an ExecutionException with my exception thrown from doInBackground()
I fixed doing this:
#Override
protected void done() {
try {
Object u = (Object) get();
//do whatever u want
} catch(ExecutionException ex) {
JOptionPane.showMessageDialog(null, "Error: "+ex.getCause().getMessage());
} catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Error: "+ex.getMessage());
}
}
I think you are wrapping your exception in another exception (which isn't in your code above). If you try out this code:
public static void main(String[] args) {
try {
throw new RuntimeException("Cannot move file");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
}
...you will see a popup that says exactly what you want.
However, to solve your problem (the wrapped exception) you need get to the "root" exception with the "correct" message. To do this you need to create a own recursive method getRootCause:
public static void main(String[] args) {
try {
throw new Exception(new RuntimeException("Cannot move file"));
} catch (Exception ex) {
JOptionPane.showMessageDialog(null,
"Error: " + getRootCause(ex).getMessage());
}
}
public static Throwable getRootCause(Throwable throwable) {
if (throwable.getCause() != null)
return getRootCause(throwable.getCause());
return throwable;
}
Note: Unwrapping exceptions like this however, sort of breaks the abstractions. I encourage you to find out why the exception is wrapped and ask yourself if it makes sense.
My guess is that you've got something in method1 which wraps one exception in another, and uses the toString() of the nested exception as the message of the wrapper. I suggest you take a copy of your project, and remove as much as you can while keeping the problem, until you've got a short but complete program which demonstrates it - at which point either it'll be clear what's going on, or we'll be in a better position to help fix it.
Here's a short but complete program which demonstrates RuntimeException.getMessage() behaving correctly:
public class Test {
public static void main(String[] args) {
try {
failingMethod();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
private static void failingMethod() {
throw new RuntimeException("Just the message");
}
}
Output:
Error: Just the message

Categories

Resources