Java Scanner 不等待输入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13374826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 12:29:28  来源:igfitidea点击:

Java Scanner does not wait for input

javauser-inputjava.util.scanner

提问by Houdini

I have two blocks of code here. One scanner properly waits user input, and the other just blows right through it and calls nextInt()which returns a NoSuchElementException. Here is the block that works:

我这里有两个代码块。一个扫描器正确等待用户输入,另一个扫描器直接通过它并调用nextInt()返回一个NoSuchElementException. 这是有效的块:

public void startGame() {
   out.println("Player1: 1 for dumb player, 2 for smart player, 3 for human player.");
   Scanner scan = new Scanner(System.in);
   p = scan.nextInt();

   if (p == 1)
        p1 = new DumbPlayer("ONE");
   if (p == 2)
        p1 = new SmartPlayer("ONE");
   else 
       p1 = new HumanPlayer("ONE");

   out.println("Player2: 1 for dumb player, 2 for smart player, 3 for human player.");
   p = scan.nextInt();

   if (p == 1)
        p2 = new DumbPlayer("TWO");
   if (p == 2)
        p2 = new SmartPlayer("TWO");
   else 
        p2 = new HumanPlayer("TWO");

   scan.close();

And here is the block that does not:

这是没有的块:

public int findBestMove(Set<Integer> moves, Board b) {

    Set<Integer> set = new HashSet<Integer>();

    out.println("Player " +name+ ", select a column from 1-7: ");
    Scanner scan = new Scanner(System.in);  <--here it should wait for input, but does not!
    int move = scan.nextInt();   <-- NoSuchElementException
    scan.close();

    for (int x = 1; x <= 7; x++) {
        set.add(move);
        move += 7;
    }
    ....etc

Both of these are separate classes, and are called from a main method in yet another class. Basically main()calls startGame(), which in turn calls the findBestMove()method of some Player class...which is where the non-working code resides. Are there times in the program where it is not appropriate to take input? I was under the impression that anytime I wanted user input, I could use this approach. Thanks!

这两个都是单独的类,并且是从另一个类中的主方法调用的。基本上main()调用startGame(),它依次调用findBestMove()某些 Player 类的方法......这是非工作代码所在的位置。程序中是否有不适合接受输入的时候?我的印象是,无论何时我需要用户输入,我都可以使用这种方法。谢谢!

回答by Denis Tulskiy

nextInt()does not discard \nin the stream, so the next call finds nothing. You have to skip it manually with Scanner.skip("\n")or Scanner.nextLine()

nextInt()不会\n在流中丢弃,因此下一次调用什么也没找到。您必须手动跳过它Scanner.skip("\n")Scanner.nextLine()

EDITAfter figuring out that "skipping readInt()" meant that the code threw an exception. and with @Andreas help, here's an alternative solution. In java6 a new class Consolehas been added for providing a better interface to stdin. And it returns a Reader that doesn't care how much you close it. So the following snippet works just fine:

编辑在弄清楚“跳过readInt()”意味着代码抛出异常之后。在@Andreas 的帮助下,这是一个替代解决方案。在 java6 中添加了一个新类Console以提供更好的 stdin 接口。它返回一个 Reader ,它不在乎你关闭它多少。所以下面的代码片段工作得很好:

    Scanner fi = new Scanner(System.console().reader());
    System.out.println(fi.nextInt());
    fi.close();

    fi = new Scanner(System.console().reader());
    System.out.println(fi.nextInt());
    fi.close();

回答by Andreas Fester

According to the java.util.Scanner javadoc, Scanner.close()closes the associated stream if this stream implements the Closeableinterface. java.lang.System.inis an InputStream, which implements the Closeableinterface. Hence, after calling Scanner.close()on a Scannerwhich is associated with System.in, the System.instream is closed and not available anymore.

根据java.util.Scanner javadocScanner.close()如果此流实现了Closeable接口,则关闭关联的流。java.lang.System.in是一个InputStream,它实现了Closeable接口。因此,在调用与 关联的Scanner.close()a之后,流将关闭并且不再可用。ScannerSystem.inSystem.in

The following SSCCE works for me. I have removed some code from the question which is not relevant to the actual issue. Note that with this approach, while it works, Eclipse gives me the warning "Resource leak: 'scan' is never closed", so a better solution would be to use one Scanner instance only.

以下 SSCCE 对我有用。我从问题中删除了一些与实际问题无关的代码。请注意,使用这种方法,虽然它有效,但 Eclipse 会给我警告"Resource leak: 'scan' is never closed",因此更好的解决方案是仅使用一个 Scanner 实例。

package com.example;

import java.util.Scanner;
import java.util.Set;
import static java.lang.System.out;

public class ScannerTest {
    int p = 0;
    String name = "Test";

    public void startGame() {
        out.println("Player1: 1 for dumb player, 2 for smart player, 3 for human player.");
        Scanner scan = new Scanner(System.in);
        p = scan.nextInt();

        out.println("Result1: " + p);

        out.println("Player2: 1 for dumb player, 2 for smart player, 3 for human player.");
        p = scan.nextInt();

        out.println("Result2: " + p);

        // scan.close();   // Do not close the Scanner to leave System.in open
    }

    public int findBestMove(Set<Integer> moves, Object /*Board*/ b) {
        out.println("Player " +name+ ", select a column from 1-7: ");
        Scanner scan = new Scanner(System.in);
        int move = scan.nextInt();
        // scan.close();   // Do not close the Scanner to leave System.in open

        out.println("Move: " + move);

        return 0;
    }

    public void run() {
        startGame();
        findBestMove(null, null);
    }

    public static void main(String[] args) {
        ScannerTest st = new ScannerTest();
        st.run();
    }
}

回答by SgtPooki

I just spent about 15 minutes troubleshooting this issue and my problem was different than all of the above.

我只花了大约 15 分钟来解决这个问题,我的问题与上述所有问题都不同。

The code is fine, but I am using Sublime Text and running it in the terminal emulator inside sublime text, on windows. This prevented the scanner from actually allowing me to try to input something.

代码很好,但我正在使用 Sublime Text 并在 Windows 上的 sublime text 内的终端模拟器中运行它。这阻止了扫描仪实际允许我尝试输入某些内容。

I ran the app using cmd and it worked fine. I hope this helps someone.

我使用 cmd 运行该应用程序,它运行良好。我希望这可以帮助别人。

回答by chAmi

Try using scan.reset();instead of scan.close(). scan.close()will throw NoSuchElementException as Denis Tulskiy said.

尝试使用scan.reset();而不是scan.close(). scan.close()正如 Denis Tulskiy 所说,将抛出 NoSuchElementException。