如何重复使用我的扫描仪?

How do I reuse my scanner?

提问人:mooL 提问时间:6/24/2016 更新时间:9/14/2023 访问量:9047

问:

我用一个方法制作了一个实用程序类,该方法接受用户输入,并返回它的小写版本,所以我没有那么多重复的代码,但它只能使用一次。在那之后,它不会扫描。我能做些什么来解决这个问题?

p.s. 我看到很多人说重复使用扫描仪是个坏主意。为什么会这样?如果扫描仪被重置了,应该不会很好吗?

public String scan() {
    String input;
    Scanner s = new Scanner(System.in);
    if (s.hasNextLine()) {
        input = s.nextLine();
    } else {
        input = "ERROR";
    }
    s.reset();
    s.close();
    return input.toLowerCase();
}
java.util.scanner

评论

2赞 Tim Biegeleisen 6/24/2016
为什么要重复使用扫描仪?你的方法在我看来很好。
0赞 waltersu 6/24/2016
将扫描仪中的输入数据保存在内存中,然后重复使用数据,而不是扫描仪。如果以后有更多输入,请使用新的扫描仪。
0赞 mooL 6/24/2016
@TimBiegeleisen我将多次调用该方法,因此必须再次使用扫描仪。除非有更好的方法,否则我不知道该怎么做
0赞 mooL 6/24/2016
@waltersu将其保存在内存中是什么意思?你说要重用哪些数据?对不起,我对 Java 很陌生
1赞 user207421 6/24/2016
您需要查找 Scanner.reset() 的实际功能。不是你想的那样。它不会重新处理已扫描的输入。

答:

0赞 Sir. Hedgehog 6/24/2016 #1

每次使用扫描仪时,您都是正确的,它会被重置。您的问题的解决方案如下:

将要传递到的所有参数添加到数组中,并在返回时使用循环将它们全部传递到,在各自的数组位置再次添加它们,以便您可以轻松地在任何地方重复使用它们。scan()forscan()

评论

0赞 Stephen C 5/17/2023
“每次使用扫描仪时,您都是正确的,它会重置” - 不确定您想说什么......但在这里没有被重置,并且对象正在被重新创建而不是重置。System.inScanner
0赞 Ahmed Amr 6/24/2016 #2

您实际上可以重复使用您的扫描仪,而不是每次需要读取一行时都创建一个新的扫描仪,下面是一个示例:

public class Test {
    public static void main(String[] args) {
        Test t = new Test();
        //create your scanner object
        Scanner s = new Scanner(System.in);
        //send it as a parameter whenever you need to read a line
        System.out.println(t.scan(s));
        System.out.println(t.scan(s));
        System.out.println(t.scan(s));
        //close it after finishing
        s.close();
    }

    public String scan(Scanner s) {
        String input;
        if (s.hasNextLine()) {
        input = s.nextLine();
        } else {
           input = "ERROR";
        }
        return input.toLowerCase();
     }
}

但是,如果您为您创建一个 reader 实用程序类,则更合乎逻辑的是 实用程序类中的实例变量。

例如:

public class Reader {
    Scanner s ;

    public Reader() {
        s = new Scanner(System.in);
    }

    public String scan() {
        String input;
        if (s.hasNextLine()) {
            input = s.nextLine();
        } else {
            input = "ERROR";
        }
        return input.toLowerCase();
    }

    public void close(){
        s.close();
    }
}

当你使用它时,它会是这样的:

public class Main {
    public static void main(String[] args) {
        //create your scanner object
        Reader r = new Reader();
        //send it whenever you need to read a line
        System.out.println(r.scan());
        System.out.println(r.scan());
        System.out.println(r.scan());
        //close it after finishing
        r.close();
    }
}

评论

0赞 mooL 6/24/2016
但是你的代码和我的代码到底有什么区别呢?我看到 s = new Scanner(System.in);与扫描方法的方法不同,但这如何改变事情,以及如何解决我做错的问题?顺便说一句,谢谢更新的答案,这正是我想要的
0赞 Ahmed Amr 6/24/2016
以这个场景为例来解释,如果你需要读取100万行,那么我们需要100万次调用扫描函数就是很常见的事情,现在的区别是你的代码会创建一个扫描器对象->然后读完行后会关闭流,这也会发生100万次,这显然是不需要的开销。在我的代码中,只为整个读取过程创建了一个 Scanner 对象,并在读取过程结束时创建了一个关闭操作。
0赞 Swapnil Padaya 1/11/2023
@AhmedAmr不能保证只创建一个扫描仪对象,但可以创建许多 Reader 对象,从而产生许多扫描仪对象。
0赞 hfontanez 11/7/2022 #3

我看到很多人说重用一个坏主意 扫描器。为什么会这样?

在大多数情况下,重用扫描程序对象并不是一个坏主意。如果没有进一步的背景,很难确定他们这么说的原因。可能是他们弄错了。也许当他们这么说时,你错误地重复使用了它。谁知道呢?

有一件事是肯定的:当您调用正在读取的对象时,您也在关闭底层输入流。而且,一旦输入流关闭,您将无法在应用程序的生命周期内重新打开它。Scanner#close()System.in

如果扫描仪被重置了,应该不会很好吗?

Scanner#reset()不会做你认为它做的事情。事实上,在此代码示例中,它不执行任何操作。此方法将 重置为 US,并将基数重置为基数 10。Locale

代码分析

public String scan() {
    String input;
    Scanner s = new Scanner(System.in);
    if (s.hasNextLine()) {
        input = s.nextLine();
    } else {
        input = "ERROR";
    }
    s.reset();
    s.close(); // BAD IDEA!!!!
    return input.toLowerCase();
}

由于我已经说过的原因,此方法只能工作一次:“一旦输入流关闭,您将无法在应用程序的生命周期内重新打开它。那么,你该怎么做呢?如果需要一遍又一遍地重用此对象,最好将其设置为类的全局属性,并且永远不要关闭它。这显然是个坏主意。因此,最好使用其他类型的输入流包装器。Scanner

也许这就是为什么其他人过去告诉您重复使用扫描仪对象是个坏主意的原因。这只是猜测。但是,从这个代码示例来看,这似乎是一个非常大的可能性。

评论

1赞 Stephen C 5/17/2023
(事实上,在某些情况下,重复使用扫描仪是一个坏主意......由于已缓冲但未被扫描程序使用的数据丢失。