I am using this link as a reference for creating custom exceptions. For my class practice, if no file is selected or passed in, my custom UnknownFileException should occur, but when I go and run my driver and put in an invalid filename I get a nullpointerexception instead?
My driver which has Adventure adventure = new Adventure(args[0]).
My custom exception:
import java.io.FileNotFoundException;
public class UnknownFileException extends FileNotFoundException {
public UnknownFileException() {
super("We couldn't tell what file this is");
}
public UnknownFileException(String message) {
super(message);
}
}
Code:
public class practice {
public String[] array;
public String line;
public PrintWriter outputStream = null;
public Scanner inputStream = null;
public practice(String fileName) throws UnknownFileException {
array = new String[100];
try {
inputStream = new Scanner(new FileReader(fileName));
line = inputStream.nextLine();
array[0] = line;
for (int i = 1; i < array.length; i++) {
array[i] = inputStream.nextLine();
}
outputStream = new PrintWriter(new
FileOutputStream("newFile.txt"));
} catch(UnknownFileException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
throw new UnknownFileException(e.getMessage());
} finally {
inputStream.close();
}
}
}
You probably got a stack trace, which should have pointed you to the line throwing the NullPointerException. I'm guessing it was this line:
inputStream.close();
The problem is that if you put in an invalid file name, new Scanner(new FileReader(fileName)) will throw, and inputStream will never be assigned. Because you have a finally block, however, before it throws your custom exception, it will try to execute the finally. But this gives a NullPointerException because inputStream is null, and that exception takes precedence, I believe (I'd have to check the language rules to make sure of what happens in this case).
Fix your finally block to test whether inputStream is null.
More: It's §14.20.2 of the JLS. This is pretty complicated, but basically if any exception is thrown from the finally block, any earlier exception thrown or caught is discarded.
inputstream is still null
Make the following change:
} finally {
if (inputStream != null) {
inputStream.close();
}
}
or use try-with-resources instead.
Related
I'm learning about Java and exception handling and the try/catch blocks. And I'm doing an example from YouTube, and I want to ask you if this is a pattern or something when you use 2 try blocks and one catch block:
private List<User> parseCSVFile(final MultipartFile file) throws Exception {
final List<User> users = new ArrayList<>();
try {
try (final BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
final String[] data = line.split(",");
final User user = new User();
user.setName(data[0]);
user.setEmail(data[1]);
user.setGender(data[2]);
users.add(user);
}
return users;
}
} catch (final IOException e) {
logger.error("Failed to parse CSV file {}", e);
throw new Exception("Failed to parse CSV file {}", e);
}
}
I try to understand why this approach is better than using a try and a catch block like this:
try (final BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
final String[] data = line.split(",");
final User user = new User();
user.setName(data[0]);
user.setEmail(data[1]);
user.setGender(data[2]);
users.add(user);
}
return users;
} catch (final IOException e) {
logger.error("Failed to parse CSV file {}", e);
throw new Exception("Failed to parse CSV file {}", e);
}
Two nested try-blocks in the first code snippet are redundant. When an exception occurs, it would be propagated until the point where it can be handled (or otherwise the execution would terminate).
Regarding the usage of try-blocks, you need to understand that it doesn't make sense having try without catch or finally (and compiler will not allow that).
Note that in case of try-with-resources try(myResource){}, you do have an implicit finally-block, therefore even without a catch-block try-with-resources can be useful and perfectly valid from the compiler perspective of view.
For more information on exception-handling refer to the official tutorial provided by Oracle.
EDIT
Looks like java changed behavior of try-with-resource, so my answer is no longer valid.
It did explains why you can see double try in some old tutorials.
ORIGINAL POST
Try with resources is syntactic sugar.
try(A a = foo()){
bar();
} catch (E e) {
}
is equivalent of
A a = foo();
try {
bar();
} catch (E e) {
} finally {
a.close();
}
Which mean exception thrown from foo won't be caught. therefore you need another try ... catch.
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.
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();
}
may i know why? i have passed in three strings to the addTab method and it is there in the variable when i debug but it says it is null why is that so? i have also instantiated the arrayList
public class STFile implements Serializable{
private ArrayList<String> qnsTitle;
private ArrayList<String> qnsImagePath;
private ArrayList<String> qnsSoundPath;
private Boolean fileExist;
//Constructor for STFile,gets existing data files if exists and load values from it to data files arraylists, if dont exist
//arraylists for data file will be instantiated.
public STFile()
{
setFileExists(checkIfAllFileExist());
if(getFileExist())
{
try {
setQnsTitle(STFile.readFile(STMain.TITLES_PATH));
setQnsImagePath(STFile.readFile(STMain.IMAGES_PATH));
setQnsSoundPath(STFile.readFile(STMain.SOUNDS_PATH));
}catch(IOException e)
{
System.out.println("in class STFile, IOEXception");
}catch(ClassNotFoundException e)
{
System.out.println("in class STFile, ClassNotFoundException");
}
}else
{
File titleFile = new File(STMain.TITLES_PATH);
File imageFile = new File(STMain.IMAGES_PATH);
File soundFile = new File(STMain.SOUNDS_PATH);
qnsTitle = new ArrayList<String>();
qnsImagePath = new ArrayList<String>();
qnsSoundPath= new ArrayList<String>();
}
}
public void addTab(String title,String imagePath,String soundPath)
{
getQnsTitle().add(title);
getQnsImagePath().add(imagePath);
getQnsSoundPath().add(soundPath);
try {
writeFiles();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("in STFile addtab Exception");
e.printStackTrace();
}
}
public static ArrayList<String> readFile(String filePath) throws ClassNotFoundException, IOException
{
ArrayList<String> arraylist = new ArrayList<String>();
ObjectInputStream obj_in = null;
FileInputStream f_in = null;
try {
f_in = new FileInputStream(filePath);
obj_in = new ObjectInputStream (f_in);
arraylist = (ArrayList<String>)obj_in.readObject();
return arraylist;
}catch(Exception e){
return null;
}finally{
f_in.close();
obj_in.close();
return null;
}
}
main method.
STFile file = new STFile();
file.addTab("Title", "image", "sound");
it keeps throwing
Exception in thread "main" java.lang.NullPointerException
at STFile.addTab(STFile.java:53)
at STMain.main(STMain.java:18)
Your readFile method will always return null, because you've got return null; in your finally block.
So if the file exists, qnsTitle (etc) will be null, causing the NullPointerException later.
I would strongly advise you not to catch Exception in the way you're doing in readFile, either. Only catch specific exceptions if you must do so at all - but in this case I wouldn't in the first place, or possibly only to wrap it in a different exception. Simply returning null from the catch block is hiding the fact that something's gone wrong, and introducing another problem further down the line. I suggest you just expand the throws clause of your method (e.g. to include IOException) and remove the catch block.
having return null; in your finally block in readFile could be the problem, try removing that.
I am trying to use a bit of code I found at the bottom of this page. Here is the code in a class that I created for it:
import java.io.LineNumberReader;
import java.io.FileReader;
import java.io.IOException;
public class LineCounter {
public static int countLines(String filename) throws IOException {
LineNumberReader reader = new LineNumberReader(new FileReader(filename));
int cnt = 0;
String lineRead = "";
while ((lineRead = reader.readLine()) != null) {}
cnt = reader.getLineNumber();
reader.close();
return cnt;
}
}
My objective is to count the lines of a text file, store that number as an integer, then use that integer in my main class. In my main class I tried a few different ways of making this happen, but (being a new programmer) I am missing something. Here is the first thing I tried:
String sFileName = "MyTextFile.txt";
private int lineCount = LineCounter.countLines(sFileName);
With this attempt I get the error "unreported exception java.io.IOException; must be caught or declared to be thrown." I don't understand why I am getting this because as I can see the exception is declared in my "countLines" method. I tried to use a try catch block right under that last bit of code I posted, but that didn't work either (I don't think I did it right though). Here is my try catch attempt:
String sFileName = "MyTextFile.txt";
private int lineCount;{
try{
LineCounter.countLines(sFileName);
}
catch(IOException ex){
System.out.println (ex.toString());
System.out.println("Could not find file " + sFileName);
}
}
Please show me the way!
Initializer block is just like any bits of code; it's not "attached" to any field/method preceding it. To assign values to fields, you have to explicitly use the field as the lhs of an assignment statement.
private int lineCount; {
try{
lineCount = LineCounter.countLines(sFileName);
/*^^^^^^^*/
}
catch(IOException ex){
System.out.println (ex.toString());
System.out.println("Could not find file " + sFileName);
}
}
Also, your countLines can be made simpler:
public static int countLines(String filename) throws IOException {
LineNumberReader reader = new LineNumberReader(new FileReader(filename));
while (reader.readLine() != null) {}
reader.close();
return reader.getLineNumber();
}
Based on my test, it looks like you can getLineNumber() after close().
The reason you are getting the the IOException is because you are not catching the IOException of your countLines method. You'll want to do something like this:
public static void main(String[] args) {
int lines = 0;
// TODO - Need to get the filename to populate sFileName. Could
// come from the command line arguments.
try {
lines = LineCounter.countLines(sFileName);
}
catch(IOException ex){
System.out.println (ex.toString());
System.out.println("Could not find file " + sFileName);
}
if(lines > 0) {
// Do rest of program.
}
}
Your countLines(String filename) method throws IOException.
You can't use it in a member declaration. You'll need to perform the operation in a main(String[] args) method.
Your main(String[] args) method will get the IOException thrown to it by countLines and it will need to handle or declare it.
Try this to just throw the IOException from main
public class MyClass {
private int lineCount;
public static void main(String[] args) throws IOException {
lineCount = LineCounter.countLines(sFileName);
}
}
or this to handle it and wrap it in an unchecked IllegalArgumentException:
public class MyClass {
private int lineCount;
private String sFileName = "myfile";
public static void main(String[] args) throws IOException {
try {
lineCount = LineCounter.countLines(sFileName);
} catch (IOException e) {
throw new IllegalArgumentException("Unable to load " + sFileName, e);
}
}
}