Main class:
public class cfung58_lab03_Main {
//main class
//creates objects
//Unhandled Exception Type FileNotFoundException occurs on the line below
static cfung58_lab03_Department myDepartment = new cfung58_lab03_Department();
...
}
Department Class:
public class cfung58_lab03_Department {
....
static cfung58_lab03_Course[] coursesArray;
static cfung58_lab03_Student[] studentArray;
public cfung58_lab03_Department() throws FileNotFoundException{
File file = new File("Courses.txt"); //file for Courses.txt
//System.out.println(file.getCanonicalPath());//gets path
//File file2 = new File("Students.txt"); //file for Students.txt
//System.out.println("True or false: " + file.canRead());
if (file.exists()){
//if the course file exists
//load scanner object to read file course.txt string
//NOTE: remember to throw FileException
Scanner read = new Scanner(file);
//count the number of Courses first before
// creating the coursesArray and filling in the elements
int numberOfCourses = 0;
while (read.hasNext()){
//String courseName = read.next();
numberOfCourses++;
}
//create coursesArray
cfung58_lab03_Course[] coursesArray = new cfung58_lab03_Course[numberOfCourses];
//restart the scanner system for read
read = new Scanner(file);
while (read.hasNext()){
String courseName = read.next();
//for loop to fill in the elements for coursesArray
for (int i = 0 ; i < numberOfCourses ; i++){
//creating element
coursesArray[i] = new cfung58_lab03_Course(courseName, 0 );
}
}
}
//else throw exception
else
throw new FileNotFoundException("File could not be found.");
I'm not exactly sure what's causing the compiler error even though I've already thrown the exception on the department constructor.
Eclipse has no solution to it either.
Any idea what might be causing this?
You're calling a method, from your horribly named main class, and this method throws a checked exception. So this exception needs to be caught (or thrown, but you can't thow it here since you're assigning a static variable out of a method):
static cfung58_lab03_Department myDepartment;
static {
try {
myDepartment = new cfung58_lab03_Department();
}
catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
That said, this field should probably be a local variable of your main method instead.
Delete " throws FileNotFoundException" and use "try&catch" to get the error. You'll be proximate to the error line.
The solution here is to create a static initialization block:
static cfung58_lab03_Department myDepartment;
static {
try {
myDepartment = new cfung58_lab03_Department();
} catch (FileNotFoundException e) {
throw new ExceptionInInitializerError(e);
}
}
Either this, or in your Department constructor, throw an unchecked exception instead.
In your code cfung58_lab03_Department you are throwing exception in else case as..
//else throw exception
else
throw new FileNotFoundException("File could not be found.");
means if your code does not found file on mentioned path it will default throw an exception.
Try following ways to get file "Courses.txt" correctly,
// Collect file with proper known path
File file = new File("resources\file_path\Courses.txt");
// Collect file with Input Stream
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("Courses.txt");
Related
I'm trying to read a text file and produce an alphabetized vocabulary list using Scanner in Java.
The one error that I'm receiving in Eclipse states that I must return a List of type String. I sort of understand why that error is occurring but unsure how to fix it.
Can anyone explain to me where I'm incorrect?
This is my current code:
public List<String> buildVocabulary(String fileName) {
Scanner scanner = null;
try {
List<String> vocab = new ArrayList<String>();
scanner = new Scanner(new FileReader(fileName));
scanner.useDelimiter("[.,;']+");
while(scanner.hasNext()) {
vocab.add(scanner.next());
}
return vocab;
}
catch (IOException e) {
fail("Got an exception");
}
finally {
if(scanner != null) {
scanner.close();
}
}
}
Test I'm trying to pass:
#Test
public void testVocabulary() {
List<String> vocab = builder.buildVocabulary("text.txt");
assertTrue(vocab.size() == 256);
assertTrue( vocab.get(0).equals("a"));
assertTrue( vocab.get(255).equals("younger"));
}
If an exception gets thrown while reading,
the return vocab might not get reached.
In this case, the method has nothing to return,
so you need to add a return statement.
You could for example move the declaration and initialization of vocab outside the try-catch and add a return vocab at the end of the method.
Or, you could return an empty list return Collections.emptyList().
Btw, you're catching IOException, but FileNotFoundException would be enough there, and more appropriate.
I'm having problems with my try-catch exception here. Actually what it does is to prompt the user for the name of a text file say, Robot.txt but if say the file does not exist, I have to make sure that the application reprompts the user for the file name. Hope you guys can understand I'm still a newbie here so please feel free to provide suggestions or advices on my coding etc. Cheers!
Main method class:
import java.io.*;
import java.util.Scanner;
import java.util.Vector;
class TestVector3 {
public static void main(String [] args)
{
System.out.println("Please enter the name of the text file to read: ");
Scanner userInput = new Scanner(System.in);
Vector <KillerRobot> robotDetails = new Vector <KillerRobot>();
KillerRobot robot;
Scanner fileInput = null;
try
{
File textFile = new File(userInput.nextLine());
fileInput = new Scanner(textFile);
}
catch (FileNotFoundException e)
{
System.out.println("Error - file not found!");
System.out.println("Re-enter file name :"); //Reprompt user for name of the text file
fileInput = new Scanner(userInput.nextLine());
}
while(fileInput.hasNext())
{
robot = new KillerRobot();
String first = fileInput.next();
robot.setName(first);
String second = fileInput.next();
robot.setMainWeapon(second);
int third = fileInput.nextInt();
robot.setNumberOfKills(third);
robotDetails.add(robot);
}
for(KillerRobot i : robotDetails)
{
System.out.println(i);
}
fileInput.close();
}
}
KillerRobot class file:
class KillerRobot {
private String name;
private String mainWeapon;
private int numberOfKills;
KillerRobot()
{
}
public String getName()
{
return name;
}
public String getMainWeapon()
{
return mainWeapon;
}
public int getNumberOfKills()
{
return numberOfKills;
}
public String toString()
{
return name + " used a " + mainWeapon + " to destroy " + numberOfKills + " enemies ";
}
public void setName(String a)
{
name = a;
}
public void setMainWeapon(String b)
{
mainWeapon = b;
}
public void setNumberOfKills(int c)
{
numberOfKills = c;
}
}
As you state that you are a beginner, let us first look at the relevant part of your code, to make sure that we talk about the same thing:
Scanner fileInput = null;
try {
File textFile = new File(userInput.nextLine());
fileInput = new Scanner(textFile);
}
catch (FileNotFoundException e) {
System.out.println("Error - file not found!");
System.out.println("Re-enter file name :");
fileInput = new Scanner(userInput.nextLine());
}
You have an input and you want to check this input for a condition and require a new input until this condition is fulfilled. This problem can be solved using a loop like the following:
Scanner fileInput = null;
do {
System.out.println("Enter file name :");
try {
fileInput = new Scanner(new File(userInput.nextLine()));
} catch (FileNotFoundException e) {
System.out.println("Error - file not found!");
}
} while(fileInput == null);
So finally, why does this work? The fileInput variable is set to null and will remain null until the given file is successfully read from standard input because an exception is thrown otherwise what prevents the fileInput variable to be set. This procedure can be repeated endlessly.
On a side note, for performance reasons, it is normally not a good idea to implement control flow that is based on exceptions. It would be better to check for a condition if a file exists via File::exists. However, if you read the file after checking for its existence, it might have been deleted in the meantime which introduces a racing condition.
Answer to your comment: In Java (or almost any programming language), you can inline expressions. This means that instead of calling two methods in two different statements as in
Foo foo = method1();
Bar bar = method2(foo);
you can simply call
Bar bar = method2(method1());
This way, you save yourself some space (what becomes more and more important if your code gets longer) as you do not need the value that you saved in foo at any other place in your code. Similarly, you can inline (which is how this pattern is called) from
File file = new File(userInput.nextLine())
fileInput = new Scanner(file);
into
fileInput = new Scanner(new File(userInput.nextLine()));
as the file variable is only read when creating the Scanner.
Try putting the try-catch in a loop like below:
Scanner fileInput = null;
while (fileInput==null)
{
try
{
System.out.println("Please enter the file name.");
File textFile = new File(userInput.nextLine());
fileInput = new Scanner(textFile);
}
catch (FileNotFoundException e)
{
System.out.println("Error - file not found!");
}
}
Next you could think of moving the File creation part into separate method, so that the code was cleaner.
Do not fall for try-catch instead add this as your functionality. Exceptions are naturally for run time error handling not for logic building.
Check if file exists at given location.
File textFile = new File(userInput.nextLine());
// Check if file is present and is not a directory
if(!textFile.exists() || textFile.isDirectory()) {
System.out.println("Error - file not found!");
//Reprompt user for name of the text file
System.out.println("Re-enter file name :");
fileInput = new Scanner(userInput.nextLine());
}
You can put while loop instead of if loop if you want to continuously prompt user until correct path is entered.
You can call back your main(), like following
try
{
File textFile = new File(userInput.nextLine());
fileInput = new Scanner(textFile);
}
catch (FileNotFoundException e)
{
System.out.println("Error - file not found!");
main(args); // recursively call main() method
}
Now if user first attempt wrong then your code will asked to re enter file name.
How to check isFile exist?
File file = new File(filePathString);
if(file.exists() && !file.isDirectory()){
System.out.println("file exist");
}
This really is an XY problem because you assumed the only way to check for a file existence is by catching a FileNotFoundException (hence asking about try-catch exception handling) whereas other means exist to help you avoid a try-catch idiom in an elegant manner.
To check if a file exists at the given path or not you can simply use the File.exists method. Please also see the File.isFile method and/or the File.isDirectory method to verify the nature of the targeted File object.
EDIT : As stated by raphw, this solution is best used in simple scenario since it can incur a race condition in the case of concurrent file deletion happening during the file existence check. See his answer for handling more complex scenario.
I am writing a function to take a text file and count how many lines it has while outputting the lines to an array of strings. Doing this I have several exceptions I need to look out for. The class function has several variables that should have a scope throughout the function but when I write a value to the function inside of an exception, the return statement cannot find it. I've moved the declaration around and nothing helps
The value returned "h5Files" "Might not have been initialized" Since I don't know how long the array will be I cannot initialize it to a certain length. I do this within the code and I need a way to tell the return statement that I now have a values
Here is the code
public String[] ReadScanlist(String fileIn){
int i;
String directory ="c:\\data\\"; // "\" is an illegal character
System.out.println(directory);
int linereader = 0;
String h5Files[];
File fileToRead = new File(directory + fileIn);
System.out.println(fileToRead);
try {
FileInputStream fin = new FileInputStream(fileToRead); // open this file
}
catch(FileNotFoundException exc) {
System.out.println("File Not Found");
}
try{
//read bytes until EOF is detected
do {
FileReader fr = new FileReader(fileToRead);// Need to convert to reader
LineNumberReader lineToRead = new LineNumberReader(fr); // Use line number reader class
//
while (lineToRead.readLine() != null){
linereader++;
}
linereader = 0;
lineToRead.setLineNumber(0); //reset line number
h5Files = new String[linereader];
while (lineToRead.readLine() != null){
h5Files[linereader] = lineToRead.readLine(); // deposit string into array
linereader++;
}
return h5Files;
}
while(i !=-1); // When i = -1 the end of the file has been reached
}
catch(IOException exc) {
System.out.println("Error reading file.");
}
try{
FileInputStream fin = new FileInputStream(fileToRead);
fin.close(); // close the file
}
catch(IOException exc) {
System.out.println("Error Closing File");
}
return h5Files;
}
Your code is very very odd. For example these two blocks make no sense:
try {
FileInputStream fin = new FileInputStream(fileToRead); // open this file
}
catch(FileNotFoundException exc) {
System.out.println("File Not Found");
}
try{
FileInputStream fin = new FileInputStream(fileToRead);
fin.close(); // close the file
}
catch(IOException exc) {
System.out.println("Error Closing File");
}
I don't know what you think they do, but besides the first one leaking memory, they do nothing at all. The comments are more worrying, they suggest that you need to do more reading on IO in Java.
Deleting those blocks and tidying the code a (moving declarations, formatting) gives this:
public String[] ReadScanlist(String fileIn) {
String directory = "c:\\data\\";
String h5Files[];
File fileToRead = new File(directory + fileIn);
try {
int i = 0;
do {
FileReader fr = new FileReader(fileToRead);
LineNumberReader lineToRead = new LineNumberReader(fr);
int linereader = 0;
while (lineToRead.readLine() != null) {
linereader++;
}
linereader = 0;
lineToRead.setLineNumber(0);
h5Files = new String[linereader];
while (lineToRead.readLine() != null) {
h5Files[linereader] = lineToRead.readLine();
linereader++;
}
return h5Files;
} while (i != -1);
} catch (IOException exc) {
System.out.println("Error reading file.");
}
return h5Files;
}
My first bone of contention is the File related code. First, File abstracts from the underlying OS, so using / is absolutely fine. Second, there is a reason File has a File, String constructor, this code should read:
File directory = new File("c:/data");
File fileToRead = new File(directory, fileIn);
But it should really be using the new Path API anyway (see below).
So, you declare h5Files[]. You then proceed to read the whole file to count the lines. You then assign h5Files[] to an array of the correct size. Finally you fill the array.
If you have an error anywhere before you assign h5Files[] you have not initialised it and therefore cannot return it. This is what the compiler is telling you.
I don't know what i does in this code, it is assigned to 0 at the top and then never reassigned. This is an infinite loop.
So, you need to rethink your logic. I would recommend throwing an IOException if you cannot read the file. Never return null - this is an anti-pattern and leads to all those thousands of null checks in your code. If you never return null you will never have to check for it.
May I suggest the following alternative code:
If you are on Java 7:
public String[] ReadScanlist(String fileIn) throws IOException {
final Path root = Paths.get("C:/data");
final List<String> lines = Files.readAllLines(root.resolve(fileIn), StandardCharsets.UTF_8);
return lines.toArray(new String[lines.size()]);
}
Or, if you have Java 8:
public String[] ReadScanlist(String fileIn) throws IOException {
final Path root = Paths.get("C:/data");
try (final Stream<String> lines = Files.lines(root.resolve(fileIn), StandardCharsets.UTF_8)) {
return lines.toArray(String[]::new);
}
}
Since I don't know how long the array will be I cannot initialize it
to a certain length.
I don't think an array is the correct solution for you then - not to say it can't be done, but you would be re-inventing the wheel.
I would suggest you use a LinkedList instead, something like:
LinkedList<String> h5Files = new LinkedList<>();
h5Files.add(lineToRead.readLine());
Alternatively you could re-invent the wheel by setting the array to an arbritary value, say 10, and then re-size it whenever it gets full, something like this:
h5Files = new String[10];
if (linereader = h5Files.size())
{
String[] temp = h5Files;
h5Files = new String[2 * linereader];
for (int i = 0; i < linereader; i++)
{
h5Files[i] = temp[i];
}
}
Either one of these solutions would allow you to initialize the array (or array alternative) in a safe constructor, prior to your try block, such that you can access it if any exceptions are thrown
Here is your problem. Please take a look on digested version of your code with my comments.
String h5Files[]; // here you define the variable. It still is not initialized.
try{
..................
do {
h5Files = new String[linereader]; // here you initialize the variable
} while(i !=-1); // When i = -1 the end of the file has been reached
..................
catch(IOException exc) {
// if you are here the variable is still not initialized
System.out.println("Error reading file.");
}
// you continue reading file even if exception was thrown while opening the file
I think that now the problem is clearer. You try to open the file and count lines. If you succeed you create array. If not (i.e. when exception is thrown) you catch the exception but still continue reading the file. But in this case you array is not initialized.
Now how to fix this?
Actually if you failed to read the file first time you cannot continue. This may happen for example if file does not exist. So, you should either return when first exception is thrown or just do not catch it at all. Indeed there is nothing to do with the file if exception was thrown at any phase. Exception is not return code. This is the reason that exceptions exist.
So, just do not catch exceptions at all. Declare your method as throws IOException and remove all try/catch blocks.
Currently trying to write a program to take input from a file and store it in an array. However, whenever I try to run the program the file cannot be found (despite file.exists() and file.canRead() returning true).
Here is my code:
public void getData (String fileName) throws FileNotFoundException
{
File file = new File (fileName);
System.out.println(file.exists());
System.out.println(file.canRead());
System.out.println(file.getPath());
Scanner fileScanner = new Scanner (new FileReader (file));
int entryCount = 0; // Store number of entries in file
// Count number of entries in file
while (fileScanner.nextLine() != null)
{
entryCount++;
}
dirArray = new Entry[entryCount]; //Create array large enough for entries
System.out.println(entryCount);
}
public static void main(String[] args)
{
ArrayDirectory testDirectory = new ArrayDirectory();
try
{
testDirectory.getData("c://example.txt");
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
(In it's current state the method is only designed to count the number of lines and create the array)
The console output is as follows: true true c:/example.txt
The program seems to throw a 'FileNotFoundException' on the line where the scanner is instantiated.
One thing I have noticed when checking the 'file' object when debugging is although it's 'path' variable has the value "c:\example.txt", it's 'filePath' value is null. Not sure if this is relevant to the issue or not
EDIT: After Brendan Long's answer I have updated the 'catch' block. The stack trace reads as follows:
java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at assignment2.ArrayDirectory.getData(ArrayDirectory.java:138)
at assignment2.ArrayDirectory.main(ArrayDirectory.java:193)
Seemingly the scanner doesn't recognize the file and thus can't find the line
This code probably doesn't do what you want:
try
{
testDirectory.getData("c://example.txt");
}
catch (Exception ex)
{
new FileNotFoundException("File not found");
}
If you catch any exception, you run the constructor for a FileNotFoundException and then throw it away. Try doing this:
try
{
testDirectory.getData("c://example.txt");
}
catch (Exception ex)
{
ex.printStackTrace();
}
According to the javadoc for Scanner, nextLine() throws this exception when there is no more input. Your program seems to expect it to return null, but that's now how it works (unlike, say, BufferedReader which does return null at the end of the input). Use hasNextLine to make sure there's another line before using nextLine.
I think it's easier to just show the code and the output I'm getting than trying to explain it :)
This is from my main method:
//prompt user for filename
System.out.println("Please enter the text file name. (Example: file.txt):");
String filename = ""; //will be used to hold filename
//loop until user enters valid file name
valid = false;
while(!valid)
{
filename = in.next();
try
{
reader.checkIfValid(filename);
valid = true; //file exists and contains text
}
catch (Exception e)
{
System.out.println(e + "\nPlease try again.");
}
}
And this is the reader.checkIfValid method:
public void checkIfValid(String filename) throws InvalidFileException, FileNotFoundException
{
try
{
in = new Scanner(new File(filename));
if (!in.hasNextLine()) // can't read first line
throw new InvalidFileException("File contains no readable text.");
}
finally
{
in.close();
}
}
This is the output I get when a nonexistent file is entered:
Please enter the text file name. (Example: file.txt):
doesNotExist.txt
java.lang.NullPointerException
Please try again.
Why is the System.out.println(e) getting a NullPointerException? When I enter an empty file or a file with text, it works just fine. The empty file prints the InvalidFileException (a custom exception) message.
When I put a try-catch statement around the "in = new Scanner(new File(filename));", and have the catch block display the exception, I do get the FileNotFoundException printed out, followed by the NullPointerException (I'm not entirely sure why the catch block in the main method would be activated if the exception was already caught in the checkIfValid method...).
I've spent a while on this and I'm completely clueless as to what's wrong. Any help would be appreciated. Thanks!
edited: I think the null pointer comes from the call to reader, it is poor practise to catch all exceptions as you no longer know where they came from!
Maybe the checkIfValid method should just check if the filename is valid?
public boolean checkIfValid(String filename) {
try {
File file = new File(filename);
return file.exists();
} catch (FileNotFoundException) {
System.out.println("Invalid filename ["+filename+"] "+e);
}
}
Then the code calling it could look like;
filename = in.next();
valid = reader.checkIfValid(filename);
if (valid)
List<String> fileContents = readFromFile(filename);
Then contain all the file reading logic in it's own method like this;
public List<String> readFromFile(filename) {
List<String> fileContents = new ArrayList<String>();
try {
in = new Scanner(new File(filename));
while (in.hasNextLine()) {
fileContents.add(in.nextLine);
}
} catch (IOException e){
//do something with the exception
} finally {
in.close();
}
return fileContents;
}
My mistake was something only I could've seen. I was catching all the exceptions so I wasn't able to see where it was coming from. Thank you for helping!