Java System.in hasNext方法仅在第一次调用时起作用

时间:2016-04-20 10:05:05

标签: java java.util.scanner system.in

这个问题令我难过。我写了一个从循环内部调用的方法。它第一次完美运行,之后就会挂起。

这是方法:

public static String promptUser(){
    String path = "";
    Scanner reader = new Scanner(System.in);  

    while (!path.contains(ROOT_FOLDER)){
        System.out.println(String.format("Please paste in the directory path from WinSCP, including %s: ", ROOT_FOLDER));

        while (true) {
            if (reader.hasNext()){
                path = reader.nextLine();
                break;
            }
        }
    }
    reader.close();
    return path;
}

这是循环

        while (true) {
        try {
            listFiles(promptUser());
            break;
        } 
        catch (Exception e) {
            e.printStackTrace();
            System.err.println(e.getMessage());
        }
    }

我第一次运行它时,会提示用户多次获取我们需要的信息(目录路径)。然后它向FTP服务器发送请求,如果该路径不存在,我希望它继续提示用户。但我的调试器在第二轮就告诉我它只是挂起:

        if (reader.hasNext()){ 

按Enter键不会让它继续。在第一次调用promptUser时,我可以输入没有根文件夹的东西,它会一直询问,直到它获得根文件夹。那么为什么不在第二次调用时这样做呢?

发生了什么事?

3 个答案:

答案 0 :(得分:2)

第一次拨打promptUser时,会执行以下操作:

  1. 创建一个包裹Scanner。{/ li>的System.in
  2. 调用hashNext,直到有数据要读取为止。
  3. 阅读一行。
  4. 关闭Scanner
  5. 退回行。
  6. 问题在于第4步。当您关闭Scanner时,您关闭System.in

    下次致电promptUser

    1. 创建包裹Scanner的另一个System.in。此时System.in已关闭。
    2. 致电hashNext(),会立即返回false ...因为Scanner包裹的信息流已关闭。
    3. 重复2. ad nauseam。你有一个无限循环。
    4. 解决方案:不要关闭System.in或包裹它的Scanner。并且不要创建包裹Scanner的第二个System.in。相反,重用原始Scanner

        

      但是有必要在某个时候关闭扫描仪吗?

      您永远不需要关闭包裹(原始)Scanner流的System.in。我们关闭流的原因是:

      • 导致写入缓冲数据(对于输出流)和
      • 以避免文件描述符泄漏。

      泄漏文件描述符的问题是进程(即您的JVM)一次只能打开一定数量的文件。如果泄漏文件描述符,您可能会发现打开文件的尝试因意外IOException而开始失败。

      System.in的情况下,没有要写入的数据。由于您无法再次打开System.in(因为您不知道它连接到的是什么),因此最多只有一个文件描述符可以被泄露"所以这不是问题

        Eclipse警告我应该这样做。

      关于关闭扫描仪等的Eclipse启发式算法相当简单。在这种情况下,警告可能是一个误报警,虽然我需要看到代码是确定的。

答案 1 :(得分:1)

获取下一个元素时,不应在循环内使用break。这会导致您的while(true)循环退出。这意味着你得到第一个项目并完成。

您应该将其更改为:

while(reader.hasNext()) {
    path = reader.nextLine();
    // do something with the path here...
}

答案 2 :(得分:-1)

阅读hasNext()

的文档

如果此扫描器的输入中有另一个标记,则返回true。在等待输入扫描时,此方法可能会阻塞。扫描仪不会超过任何输入。 返回: 当且仅当此扫描器具有另一个令牌时才为真

所以,hasNext()等着你输入一些值。它会等到找到用户输入的单个字符串。