2

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;
}
}
Scorpiorian83
  • 469
  • 1
  • 4
  • 17

5 Answers5

3

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.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • 1
    Down voters: I assume those are revenge down votes. Otherwise, please clarify your critic. – Rafael Winterhalter Aug 18 '14 at 08:27
  • oh hey hi thank you so much for guiding me along erm may i ask you about this line of code `fileInput = new Scanner(new File(userInput.nextLine()));` I don't quite get it though. Why would you put the words new file in the line? am i able to research on that? cheers! :D – Scorpiorian83 Aug 18 '14 at 08:47
2

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.

Michał Schielmann
  • 1,372
  • 8
  • 17
1

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.

SaurabhJinturkar
  • 554
  • 7
  • 20
  • thanks for helping anyway but i'm self learning on past school work and it states i have to use the `try-catch exception` :D – Scorpiorian83 Aug 18 '14 at 08:37
0

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");
  }
Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
0

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.

Community
  • 1
  • 1
m4rtin
  • 2,445
  • 22
  • 34
  • OP don't wanna logic to check file exists. He want to give a message and asked user to re enter file name if first attempt wrong. Read question carefully. – Ruchira Gayan Ranaweera Aug 18 '14 at 08:18
  • Please tell me in which case the user must re-enter the file name ? :) – m4rtin Aug 18 '14 at 08:20
  • asked user to re enter file name if first attempt contains wrong file name. Read question carefully. – Ruchira Gayan Ranaweera Aug 18 '14 at 08:27
  • Exactly, and how do you check if the file name is wrong ? – m4rtin Aug 18 '14 at 08:28
  • You can use `File file = new File(filePathString); if(fileexists() && !file.isDirectory())` to check that. And currently OP asking to how to use recursion. – Ruchira Gayan Ranaweera Aug 18 '14 at 08:30
  • Right again ! So you see, my answer isn't that bad after all ;) Although I do not believe OP is really asking for recursion, I saw your post and while an interesting solution, I believe a recursion on the main function will do more harm than good because why code a complex solution when you can solve the same problem with a little *if* condition ? – m4rtin Aug 18 '14 at 08:33
  • 1
    @RuchiraGayanRanaweera The OP is **not** asking for how to use recursion, he is asking for how to repeat the promt for the file name. As I explained in the comment to your answer, recursion is a bad solution for solving this problem. Also, the explicit check is flawed as I explained in a comment to another answer. – Rafael Winterhalter Aug 18 '14 at 08:46
  • @raphw +1, you are completely right though I think OP is not at the point where he should worry about racing condition with concurrent file deletion hence my answer. I think he just wanted an answer to complete a simple program but in a more complex architecture where this particular problem could arise, your answer would be better. – m4rtin Aug 18 '14 at 08:56
  • @m4rtin This might be correct concerning today's state of learning, however as SO being somewhat an archive for solutions to problems, one should still mention these problems for anybody that reads the answers. Learning how to program is a process where you always learn new things. It should at least be pointed out to the OP that a *simple solution* might bear problems, otherwise, this learned intermediate pattern soon evolves into a bad habit as the OP continues to write more advanced application where he relies on incomplete information he picket up from here. – Rafael Winterhalter Aug 18 '14 at 09:01