Reputation: 1198
public static Scanner getFileScanner()
{
try{
Scanner input = new Scanner(System.in);
String file = input.nextLine();
Scanner fs = new Scanner(new FileReader(file));
}catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
getFileScanner();
}finally{
return fs;
}
}
I keep getting the error that the variable fs isn't found. I can't figure out why for the life of me.
Upvotes: 0
Views: 622
Reputation: 719248
Lets start by listing the problems in your code:
The compilation error on the return
statement is caused by fs
being out of scope as described in other answers.
When you make the recursive call to getFileScanner()
, you don't assign or return the result. So it won't make it back to the caller.
Using a return
in a finally
block is a bad idea. It will squash (throw away) any other exceptions that might be propagating at that point; e.g. exceptions that don't match a catch
or exceptions thrown in a catch
block.
The input.nextLine()
call will throw an exception if the underlying stream has reached the EOF; e.g. the user typed [CONTROL]+D or whatever. You don't have to catch it (it is unchecked), but the return in the finally
block squashes it (probably) resulting in the caller getting a null
instead. Ughh ...
Hard-wiring System.in
and System.out
makes your method less reusable. (OK, this may not be an issue you should address in this particular case. And I won't, below ...)
In theory, your method could be made to throw a StackOverflowError
; e.g. if the user hits [ENTER] a number of times. This problem is inherent in your recursive solution, and is a good reason not to do it that way.
Finally, here's a version of the method that addresses these problems:
public static Scanner getFileScanner() throws NoSuchElementException
{
Scanner input = new Scanner(System.in);
while (true) {
String file = input.nextLine();
try {
return new Scanner(new FileReader(file));
} catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
}
}
}
Note that I've replaced the recursion, gotten rid of the finally
, and declared the exception that is thrown. (One could catch that exception and either report it, or rethrow it as an application specific exception.)
Upvotes: 1
Reputation: 110084
Variables declared inside a try
block are not in scope inside the corresponding finally
block. There are a number of issues with your approach in general... it's generally not a good idea to return
inside a finally
block, for example.
Here's what I'd do:
public static Scanner getFileScanner() {
Scanner input = new Scanner(System.in);
File file = null;
while (true) {
file = new File(input.nextLine());
if (file.exists() && file.isFile())
break;
System.out.println("Invalid filename. Try another:");
}
return new Scanner(new FileReader(file));
}
Upvotes: 1
Reputation: 546
Just to expand on what the other guys indicated with their code samples...
Because you declare the fs
variable within the try
block the variable will only be scoped (visible) within the braces immediately after the try
keyword.
By moving the fs
variable declaration out of the try block and into the getFileScanner
method body you are ensuring that the variable can be accessed by all blocks within the method body (try
, catch
and finally
blocks).
Hope that helps!
Upvotes: 0
Reputation: 82589
Declare it first:
public static Scanner getFileScanner() {
Scanner input = new Scanner(System.in);
Scanner fs = null;
while(fs == null) {
try{
String file = input.nextLine();
Scanner fs = new Scanner(new File(file));
}catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
}
}
return fs;
}
Upvotes: 0
Reputation: 30226
You declared fs in the try block and try to access it in a different scope (the finally block). The usual paradigms is to declare fs before the try block as null.
Upvotes: 0
Reputation: 40176
Your fs
is declared under try
block... to fix this, declare it outside the block:-
Scanner fs = null;
try {
...
fs = new Scanner(new FileReader(file));
}
catch (FileNotFoundException fe) {
...
}
finally {
return fs;
}
Upvotes: 1