Using custom exception in Java - java

I am trying to throw my custom exception in java but currently I have had no luck. I have two classes a readWrite class which allows the user to enter the file name and a text to be wrote to the file (via the constructor). It has three methods, write, read and a writeToFile which validates if the file ends in .txt if it does now it should throw my custom exception class stating that "Sorry but this system only accepts .txt files" which I have created in a toString() method in my custom exception. I can not seem to make it work, below is the code, some might be able to help, I hope I have explained properly as I am new to Java, note I have commented out some code as I was trying a few different things to make it work
ReadWrite.java
import java.io.*;
public class ReadWrite
{
private final String file;
private final String text;
public ReadWrite(String file, String text)
{
// initialise instance variables
this.file=file;
this.text=text;
}
private void write() //throws InvalidFileException
{
try {
FileWriter writer = new FileWriter(file);
writer.write(text);
writer.write('\n');
writer.close();
}
catch(IOException e)
{
System.out.print(e);
}
}
public boolean writeToFile()
{
boolean ok;
try{
FileWriter writer = new FileWriter(file);
{
if(file.toLowerCase().endsWith(".txt"))
{
write();
ok = true;
} //if end
else{
ok=false;
//throw new InvalidFileException();
} //else end
}
} //try end
catch(IOException e) {
ok=false;
} // catch end
//catch (InvalidFileException e){
//System.out.println(e.toString());
//}
return ok;
}
public void read(String fileToRead)
{
try {
BufferedReader reader = new BufferedReader(new FileReader(fileToRead));
String line = reader.readLine();
while(line != null) {
System.out.println(line);
line = reader.readLine();
}// while end
reader.close();
}//try end
catch(FileNotFoundException e) {
System.out.println(fileToRead + " the system can not find the file specified");
} //catch end
catch(IOException e) {
e.printStackTrace();
} //catch end
}
}
InvalidFileException.java
import java.io.FileNotFoundException;
import java.io.*;
public class InvalidFileException extends Exception
{
/**
* Constructor for objects of class InvalidFileException
*/
public InvalidFileException(String message)
{
super(message);
}
public String toString()
{
return ("Sorry but this system only accepts .txt files");
}
}

try this:
private void write() throws InvalidFileException {
try {
if(!file.getName().endsWith(".txt") {
throw new InvalidFileException(".txt files only.");
}
FileWriter writer = new FileWriter(file);
writer.write(text);
writer.write('\n');
writer.close();
}
catch(IOException e)
{
// handle exception please.
}
Please note, that you have to override the "getMessage()" Method of Exception in order to print your custom message. Or set it in the super() call.
Overriding the toString() method makes your super() call and therefore your custom (detail) message passed to the exception (in my example ".txt files only.") obsolete, because this string won't be printed anymore.

Below is your requirement:
it does not it should throw my custom exception class stating that
"Sorry but this system only accepts .txt files"
I think you got confused because of toString. You really don't need that toString method. You correctly implemented a InvalidFileException which accepts a String argument.
So, now all you need is throw new InvalidFileException("Sorry but this system only accepts .txt files"); or use whatever String message you want while throwing InvalidFileException.
Please note, if you are throwing an exception from a method and catching it in same method looks illogical unless you are doing because APM (application performance monitoring) tools logging purpose.
As other note, if you are throwing exception like this then you need to add a throw statement in your method signature indicating that this method "may" throw so-and-so exception. So, that called of that method can either re-throw or catch it.
If you are catching the exception somewhere then use getMessage method on the exception object and you will get same message as you placed while throwing the exception, in this case - "Sorry but this system only accepts .txt files"

InvalidFileException extends Exception but you only ever try to catch IOException and FileNotFoundException. I think you meant to have InvalidFileException extend IOException.

Related

Handling FileNotFoundException in a different file

It's been a while since I've used Java so I feel silly that this is confusing me, but I have a class 'FileProcessor' in a 'FileProcessor.java' file. I'm trying to use it in my 'Driver.java' file but I keep getting this error:
error: unreported exception FileNotFoundException; must be caught or declared to be thrown
I'm a little confused by the whole exceptions thing in Java and I thought I handled it in my FileProcessor.java file but I don't know.
FileProcessor.java
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileNotFoundException;
public class FileProcessor{
/**
* Reads one line from file
* #param arg A file
* #return The line that is read
*/
public String readLineFromFile(File f) throws FileNotFoundException,
IOException{
BufferedReader br = null;
String line;
try{
br = new BufferedReader(new FileReader(f));
line = br.readLine();
return line;
}
catch(IOException e){
e.printStackTrace();
System.err.println("Read method failed");
throw new IOException();
}
catch(FileNotFoundException e1){
e1.getMessage();
System.err.println("File is not found");
throw new FileNotFoundException();
}
}
}
Driver.java
import java.io.File;
import java.io.FileNotFoundException;
public class Driver{
public static void main(String args[]){
File inFile = null;
if (0 < args.length){
inFile = new File(args[0]);
}
else{
System.err.println("No input file found");
System.exit(0);
}
FileProcessor fileProcessor = new FileProcessor();
String lineRead;
try{
lineRead = fileProcessor.readLineFromFile(inFile);
}
catch(FileNotFoundException e){
throw new FileNotFoundException();
}
}
}
Your main throws a new FileNotFoundException in the catch block which can't be catched outside of main. Change:
import java.io.File;
import java.io.FileNotFoundException;
public class Driver{
public static void main(String args[]){
File inFile = null;
if (0 < args.length){
inFile = new File(args[0]);
}
else{
System.err.println("No input file found");
System.exit(0);
}
FileProcessor fileProcessor = new FileProcessor();
String lineRead;
try{
lineRead = fileProcessor.readLineFromFile(inFile);
}
catch(FileNotFoundException e){
System.out.print(e.getMessage());
}
}
}
Throwing a new IO- or FileNotFoundException when you catch them is not a good handling of this exceptions.
catch(IOException e){
e.printStackTrace();
System.err.println("Read method failed");
throw new IOException();
}
First, you loose the Exception information (which file can not be found, what exactly happened, ...). Second, it does not really catch them if you throw it again, so you have to catch them again one frame above.
So, the simplest possible solution is to delete the throw statement.
public class FileProcessor{
public String readLineFromFile(File f)
// this can be deleted if you catch the exceptions
// in here (and do not rethrow them)
// throws FileNotFoundException, IOException
{
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(f));
return br.readLine();
} catch(IOException e) {
e.printStackTrace();
// throw new IOException();
}
// this can be deleted because FileNotFoundException is a
// subclass of IOException and is caught above
// catch(FileNotFoundException e1){
// e1.getMessage();
// System.err.println("File is not found");
// throw new FileNotFoundException();
// }
// and after all, you should close the BufferedReader
// or use the "try-with-resources"
finally {
if(br != null) { br.close(); }
}
}
}
There are few things to do with Exceptions.
You catch the Exception and you write your appropriate code needed to handle the Exception, Example logging, setting error message or triggering fail mail, retry with new file name etc. For this you write the catch block along with try.
2.You catch the Exception and you write your appropriate code needed to handle the Exception, Example logging etc but you want future code which calls your method to catch and process the exception again. In this case you will re throw the exception using throw new and add it in throws. you can even throw new Exception type like
catch(NullPointerException e) {
throw new RecipeNotFoundException("No recipe found");
}
Delay the handling to future code which calls this method. This is done by writing throws clause. Throws tell method(s) calling a method that there are possibilities an exception can occur here and it is not caught and you need to catch and you wont write catch.
In your code you have caught the code in FileProcessor.readLineFromFile(File) method but you have also added throws clause to the method. So the system thinks there are chances an exception can be re thrown and not caught possible another FileNotFoundException from the catch block.
One more thing after catching the Exception you have re thrown same exception throw new IOException(); and throw new FileNotFoundException(); remove that too.
If you go through Java documentation on FileNotFoundException and IOException here. docs.oracle.com/javase/7/docs/api/java/io/… and docs.oracle.com/javase/7/docs/api/java/io/IOException.html you will notice FileNotFoundException actually extends IOException so you do not have to actually catch FileNotFoundException.

how to get the filename of a thrown IOException in 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!

Junit Test case of method that already has a try-catch clause

I'm trying to write a test case for the method setTrailer() within the class ErParser. setTrailer() has try-catch clauses, and in one of its catch clauses, it catches NullPointerException. I'm trying to write a Junit test for the case where setTrailer() throws and catches a NullPointerException, but the test case keeps failing. Is it because I already caught the exception in the method itself? Should I be catching the exception in the test case instead?
The test case:
public class TestERParser {
#Test(expected=NullPointerException.class)
public void nullSetTrailer() {
ERParser recCurrParse = new ERParser();
recCurrParse.setTrailer(null);
}
}
setTrailer() method within the ERParser Class:
public class ERParser {
private static final String TRAILER_E = "GRAND TOTAL";
private static final String TRAILER_R = "TRAILER";
public String trailerRecord;
/**
* Constructs an ERParser object.
*/
public ERParser() {
this.trailerRecord = null;
this.trailerVals = null;
}
/**
* Populates the trailerRecord field with the summary (trailer) record of the input file.
* #param file Input file
* #throws NullPointerException, FileNotFoundException, IOException
*/
public void setTrailer(File file) {
try {
FileReader fReader = new FileReader(file);
BufferedReader bReader = new BufferedReader (fReader);
String currLine = new String();
readLoop:
while (bReader.ready()) {
currLine = bReader.readLine();
if (currLine.contains(TRAILER_E) || currLine.contains(TRAILER_R)) {
break readLoop;
}
}
this.trailerRecord = currLine.trim();
System.out.println("From setTrailer(): " + this.trailerRecord);
fReader.close();
bReader.close();
} catch (NullPointerException exception) {
exception.printStackTrace();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} catch (IOException exception) {
exception.printStackTrace();
}
}
}
As you suspected you are catching the NPE inside of your code and it is not being propagated. If you expected your users to catch this exception you should remove this code and adorn your method with throws, to the appropiate classes.
public void setTrailer(File file) throws Exception {
FileReader fReader = new FileReader(file);
BufferedReader bReader = new BufferedReader (fReader);
String currLine = new String();
readLoop:
while (bReader.ready()) {
currLine = bReader.readLine();
if (currLine.contains(TRAILER_E) || currLine.contains(TRAILER_R)) {
break readLoop;
}
}
this.trailerRecord = currLine.trim();
System.out.println("From setTrailer(): " + this.trailerRecord);
fReader.close();
bReader.close();
}
As your code now throws a checked Exception, you will need to update your Junit method slightly, to catch the checked exceptions
#Test(expected=NullPointerException.class)
public void nullSetTrailer() throws Exception {
ERParser recCurrParse = new ERParser();
recCurrParse.setTrailer(null);
}
We can argue about whether or not this catch block means the exception is handled. I would argue that merely printing the stack trace is not handling anything. It might be better to add a throws clause to the method signature and let clients decide what to do with exceptions.
If the method is written that way, it's up to you to test it as-written. You wouldn't have a choice if this was a 3rd party library.
Write the test that throws the exception; succes means trailerRecord is set to null.
Your code has another flaw: close the streams in a finally block. You risk not closing the input stream properly as written.
In your test case are expecting a NullPointerException class. If you catch it, the caller class will not get it. Hence, either you can remove the try/catch blocks or you can rethrow the exception after printing stacktrace :
catch (NullPointerException exception) {
exception.printStackTrace();
throw new NullPointerException();
}

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
}
}

Java abstract class "instance variables"

I don't know if my mind just fools me or this is really not working.
I need different type of Logging-classes so I created a abstract-class, the only definition that all classes will have the same is the way the writeToLog is handled:
public abstract class LoggerTemplate {
protected String filename ="log/";
protected File logfile;
protected FileWriter fw;
public void writeToLog(String message) {
if(fw != null) {
try {
message = new SimpleDateFormat("dd-MM-hh:mm").format(new Date()) + " " + message;
fw.write(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The concrete sub-classes will implement rest of the logic in their constructor, ie one of them:
public class JitterBufferLogger extends LoggerTemplate {
public JitterBufferLogger() {
super();
filename += new SimpleDateFormat("yyyyddMMhhmm'.log'").format(new Date());
if(!new File("log/").exists())
new File("log").mkdir();
logfile = new File(filename);
try {
logfile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
try {
fw = new FileWriter(logfile);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
But when I debug I can see that when calling the writeToLog for a specific logger, it jumps into the LoggerTemplate method, and therefore fw and logfile are null. So it's not working.
Isn't it supposed to work or do I just mess something a bit up and should go into weekend ;-)
It should work, it is normal, that the debugger stepped into the LoggerTemplate class upon entering the writeToLog() method. What is strange that the attributes in the base class have null values.
I have tested your code with the following short test program:
public class Test {
public static void main(String[] args) {
LoggerTemplate lt = new JitterBufferLogger();
lt.writeToLog("Hello");
}
}
After adding fw.flush() to the LoggerTemplate.writeToLog() method just after the fw.write() call, it worked for me, the log file had been created and it contained the log message.
Maybe the new File("log").mkdir() or some other calls throw an exception which you cannot see, because stderr had been redirected somewhere.
So what may be missing?
- filewriter flushing could have helped.
- I can't reproduce the null values with the original code, don't know what happened.
- but as everybody, including me, said: it should work and it does.
Why was nothing in the logfile?
- maybe the flush of fw was missing..
anyhow I wrapped it with a Printwriter:
public abstract class LoggerTemplate {
protected String filename ="log/";
protected File logfile;
protected PrintWriter pw;
public void writeToLog(String message) {
try {
pw = new PrintWriter(new FileWriter(logfile,true));
message = new SimpleDateFormat("dd-MM-hh:mm").format(new Date()) + " " + message + "\n";
pw.write(message);
pw.flush();
pw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and now it's working like it should and was expected to be.
Note that the fw instantiation in the concrete sub-classes is not needed anymore.

Categories

Resources