在不推进扫描仪的情况下获取Java扫描仪输入

时间:2018-11-30 16:23:07

标签: java input reflection token java.util.scanner

在不提高扫描仪价值的情况下获取它的价值-Java

我想获取扫描器中输入的值而无需提前。当前,我将扫描仪输入用作System.in

final var sc = new Scanner(System.in);

我知道扫描器上的hasNext方法,它们是我目前最好/唯一的检查输入而不进行输入的方法。

例如,这就是我如何确保从sc获得正整数输入的原因。

public static int getPositiveIntegerInput(Scanner sc) {
    System.out.println("Please input a positive integer");
    sc.useDelimiter("\n");
    while (!sc.hasNextInt() || sc.hasNext(".*[^\\d].*")) {
        System.out.println("Invalid input, please try again");
        sc.nextLine();
    }
    return sc.nextInt();
}

我想将检查sc的输入而不提前的概念扩展到实际上获得sc的输入而无需提前的输入。

到目前为止我已经尝试过的

我已经详细介绍了hasNext()Scanner的实现细节。

hasNext的实现:

public final class Scanner {

    public boolean hasNext(Pattern pattern) {
        ensureOpen();
        if (pattern == null)
            throw new NullPointerException();
        hasNextPattern = null;
        saveState();
        modCount++;

        while (true) {
            if (getCompleteTokenInBuffer(pattern) != null) {
                matchValid = true;
                cacheResult();
                return revertState(true);
            }
            if (needInput)
                readInput();
            else
                return revertState(false);
        }
    }
}

至少在我看来,可以从方法getCompleteTokenInBuffer获取扫描仪的输入,但实际上我并不真正了解它的工作原理。我不知道该方法是否仅在不推进扫描器的情况下就获得了扫描器的价值,或者是否将其推进了,然后其他方法将其还原为输入之前的状态,好像它根本没有推进。将它与其他东西结合在一起,或者实际上结合在一起。

我一直在通过Java的反射API调用私有方法Scanner,以尝试实际返回持有sc输入值的令牌而没有实际推进方法(但老实说,我只是在玩它,不知道如何实际完成我想做的事情。

public static void main(String[] args) {

    final var sc = new Scanner(System.in);
    sc.useDelimiter("\n");

    var str = "";

    try {
        Method method = Scanner.class.getDeclaredMethod("getCompleteTokenInBuffer", Pattern.class);
        method.setAccessible(true);
        str = (String) method.invoke(sc, Pattern.compile(".*"));
    } catch (Exception e) {
        System.out.println("Well, that didn't work!");
        System.out.println("Exception: " + e);
    }

    System.out.println("getCompleteTokenInBuffer: " + str);

    // Prints: "getCompleteTokenInBuffer: null"
}

注意:上面的方法在获取sc的输入值之前不会等待输入,因此返回的值为null

目标:

只需重申一下,我想寻找并实际推进Scanner对象的输入值。

1 个答案:

答案 0 :(得分:1)

您正在寻找的东西可能被称为偷看功能。

This answer在另一个线程上表示您可能会通过围绕Scanner创建一个包装类来实现此功能,因为Scanner类本身并未实现该包装类。