在 java 中递归构建带有嵌入式 FileReader 的扫描仪

发布于 2024-10-17 22:20:26 字数 439 浏览 6 评论 0原文

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

我不断收到变量 fs 未找到的错误。我一生都无法弄清楚为什么。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

雪落纷纷 2024-10-24 22:20:26

您的 fs 是在 try 块下声明的...要解决此问题,请在块之外声明它:-

Scanner fs = null;
try {
    ...
    fs = new Scanner(new FileReader(file));
}
catch (FileNotFoundException fe) {
    ...
}
finally {
    return fs;
}

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;
}
乖乖公主 2024-10-24 22:20:26

try 块内声明的变量不在相应的 finally 块内的范围内。一般来说,您的方法存在许多问题......例如,在 finally 块内 return 通常不是一个好主意。

这就是我要做的:

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

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));
}
橘香 2024-10-24 22:20:26

让我们首先列出代码中的问题:

  1. return 语句上的编译错误是由 fs 超出其他答案中所述的范围引起的。

  2. 当您递归调用 getFileScanner() 时,您不会分配或返回结果。因此它不会返回给调用者。

  3. finally 块中使用 return 是一个坏主意。它将压制(丢弃)此时可能传播的任何其他异常;例如,与 catch 不匹配的异常或在 catch 块中引发的异常。

  4. 如果底层流已到达 EOF,则 input.nextLine() 调用将引发异常;例如,用户输入 [CONTROL]+D 或其他内容。您不必必须捕获它(它是未经检查的),但是finally块中的返回会挤压它(可能)导致调用者得到null 相反。呃...

  5. 硬连线 System.inSystem.out 使您的方法的可重用性降低。 (好吧,在这种特殊情况下,这可能不是您应该解决的问题。而且我不会,如下...)

  6. 理论上,您的方法可以抛出 StackOverflowError ;例如,如果用户多次点击 [ENTER]。这个问题是你的递归解决方案所固有的,并且是不这样做的一个很好的理由。

最后,这是解决这些问题的方法的一个版本:

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:");
        }
    }
}

请注意,我已经替换了递归,摆脱了finally,并声明了引发的异常。 (可以捕获该异常并报告它,或者将其作为应用程序特定的异常重新抛出。)

Lets start by listing the problems in your code:

  1. The compilation error on the return statement is caused by fs being out of scope as described in other answers.

  2. 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.

  3. 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.

  4. 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 ...

  5. 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 ...)

  6. 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.)

寄人书 2024-10-24 22:20:26

您在 try 块中声明了 fs 并尝试在不同的范围(finally 块)中访问它。通常的范例是在 try 块之前将 fs 声明为 null。

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.

╰ゝ天使的微笑 2024-10-24 22:20:26

先声明一下:

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

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;
}
只是我以为 2024-10-24 22:20:26

只是为了扩展其他人在他们的代码示例中指出的内容...

因为您在 try 块中声明了 fs 变量,所以该变量的作用域仅在以下范围内(可见) try 关键字后面的大括号。

通过将 fs 变量声明移出 try 块并移入 getFileScanner 方法主体,您可以确保该变量可以被方法主体内的所有块访问(>trycatchfinally 块)。

希望有帮助!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文