【问题标题】:How can I clear the Scanner buffer in Java?如何清除 Java 中的扫描仪缓冲区?
【发布时间】:2012-05-23 03:57:25
【问题描述】:

我有这样的事情:

    Scanner in=new Scanner(System.in);
    int rounds = 0;
    while (rounds < 1 || rounds > 3) {
        System.out.print("How many rounds? ");
        if (in.hasNextInt()) {
            rounds = in.nextInt();
        } else {
            System.out.println("Invalid input. Please try again.");
            System.out.println();
        }
        // Clear buffer
    }
    System.out.print(rounds+" rounds.");

如何清除缓冲区?

编辑:我尝试了以下方法,但由于某种原因它不起作用:

while(in.hasNext())
    in.next();

【问题讨论】:

  • “清除缓冲区”是什么意思?清除控制台(如 cls dos 命令)?
  • 我正在寻找类似的东西:while(in.hasNext()) in.next();。由于某种原因,该循环不起作用。

标签: java io


【解决方案1】:

试试这个:

in.nextLine();

这会使扫描器前进到下一行。

【讨论】:

  • 有时输入多行,这仅适用于一行。
  • 你会认为 hasNextLine(或 hasNext)可以用来检查是否有更多的输入可用,但这在 Java 中不起作用。 hasNextLine/hasNext 方法总是为键盘 (System.in) 返回 true。我发现清除所有缓冲数据而不阻塞的唯一方法是打开一个新的扫描器:in.close(); in = new Scanner(System.in);
  • @Georgie 您可能希望在不关闭旧扫描仪的情况下创建新扫描仪。关闭 Scanner 也会关闭底层可读(在我们的例子中是 System.in),所以如果我关闭 System.in Scanner 并创建另一个 Scanner.next(),我会在下次调用 Scanner.next() 时得到 NoSuchElementExceptions。如果你真的需要关闭旧的,this StackOverflow answer 建议你可以通过为 System.in 创建一个包装器来解决这个问题,如果你想先关闭它。
  • @SansWit 在 Java 8 update 211、Windows 7 上为我工作。可能在不同的 JVM 实现/Java 版本中行为不同,这会很糟糕。
【解决方案2】:

您不能明确清除 Scanner 的缓冲区。在内部,它可能会在读取令牌后清除缓冲区,但这是程序员无法触及的实现细节。

【讨论】:

    【解决方案3】:

    这应该可以解决它...

    Scanner in=new Scanner(System.in);
        int rounds = 0;
        while (rounds < 1 || rounds > 3) {
            System.out.print("How many rounds? ");
            if (in.hasNextInt()) {
                rounds = in.nextInt();
            } else {
                System.out.println("Invalid input. Please try again.");
                in.next(); // -->important
                System.out.println();
            }
            // Clear buffer
        }
        System.out.print(rounds+" rounds.");
    

    【讨论】:

      【解决方案4】:

      使用以下命令:

      in.nextLine();
      

      紧接着

      System.out.println("Invalid input. Please Try Again.");
      System.out.println();
      

      或在以下大括号之后(您对此的评论所在的位置)。

      此命令将扫描仪前进到下一行(从文件或字符串读取时,这只是读取下一行),因此在这种情况下实质上是刷新它。它清除缓冲区并使扫描仪准备好接受新的输入。当用户输入无效输入(例如当要求输入数字时的字母)时,它可以最好地用于清除当前缓冲区。

      方法的文档可以在这里找到: http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#nextLine()

      希望这会有所帮助!

      【讨论】:

        【解决方案5】:

        其他人建议使用in.nextLine() 清除缓冲区,这适用于单行输入。然而,正如 cmets 指出的那样,有时 System.in 输入可以是多行的。

        如果您使用的是 System.in 而不是其他 InputStream,您可以创建一个新的 Scanner 对象来清除缓冲区。

        in = new Scanner(System.in);

        如果您这样做,不要先致电in.close()。这样做会关闭 System.in,因此您将在后续调用 in.nextInt();System.in 时收到 NoSuchElementExceptions,可能不应该在您的程序期间关闭。

        (上述方法特定于 System.in。它可能不适用于其他输入流。)

        如果您确实需要在创建新对象之前关闭 Scanner 对象,this StackOverflow answer 建议为 System.in 创建一个 InputStream 包装器,该包装器具有自己的 close() 方法,不会关闭包装的 System.in 流。不过,这对于简单的程序来说是多余的。

        【讨论】:

        • 创建一个新的 Scanner 对象是最好的建议!但是,请确保没有对旧扫描仪对象的引用,以便可以收集垃圾。
        【解决方案6】:
        scan.nextLine();
        

        在读取字符串输入之前放上一行

        【讨论】:

        • OP 的代码中没有scan 变量,他们的扫描仪名称是in。此外,该解决方案已在多个答案中提出。
        猜你喜欢
        • 2014-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-10
        • 1970-01-01
        • 1970-01-01
        • 2020-04-11
        • 1970-01-01
        相关资源
        最近更新 更多