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

3
我创建了一个实用类,其中包含一个方法,接受用户输入并返回其小写版本,以减少重复代码。但是该方法只能使用一次。之后它将无法扫描。我该如何解决这个问题?
附言:我看到很多人说重复使用扫描器是不好的主意。为什么会这样?如果重置扫描器,那不应该没问题吗?
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();
}

2
你为什么想要重复使用扫描器呢?你的方法看起来很好。 - Tim Biegeleisen
重复使用扫描器不是一个好主意吗?创建数百个扫描器来读取数百行会更好吗?当然,您可以重复使用它,例如将您的行放入数组中。 - eldo
1
你需要查阅一下 Scanner.reset() 的实际作用,而不是你所想的。它不会重新处理已经被扫描过的输入。 - user207421
@eldo,你是在说将s作为数组吗?比如 Scanner s[] = new Scanner(System.in); 还是 input[] = s.nextline(); - mooL
@mooL 我建议你仔细阅读我的回答。这里发布的其他答案都很好,但并没有完全回答你的问题。 - hfontanez
显示剩余5条评论
3个回答

0
每次使用扫描仪时您都是正确的,它都会被重置。解决您问题的方法如下:
将要传递给scan()的所有参数添加到数组中,并使用for循环将它们全部传递给scan()。在返回时,将它们再次添加到它们相应的数组位置,这样您就可以在任何地方轻松地重复使用它们。

每次使用扫描器时,您都是正确的,它会被重置。我不确定您想要表达什么...但是在这里System.in没有被重置,而是重新创建了Scanner对象。 - Stephen C

0
你其实可以重复使用 Scanner 而不是每次需要读取一行时都创建一个新的,这里是一个示例:
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();
     }
}

但是如果为您创建一个读取器实用程序类,将其作为实用程序类的实例变量更为合理。

例如:

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();
    }
}

但是你的代码和我的代码有什么区别呢?我看到s = new Scanner(System.in);不在与scan方法相同的方法中,但这会改变什么,它又如何修复我做错的地方?顺便说一句,谢谢更新的答案,这正是我需要的。 - mooL
拿这个场景来解释,如果你需要读取100万行,那么我们需要100万次调用扫描函数,这是很常见的事情,现在的区别是你的代码将创建一个扫描器对象->然后在读取完行后关闭流,这将发生100万次,这显然是不必要的开销。在我的代码中,只创建了一个扫描器对象用于整个读取过程,并在读取过程结束时进行一次关闭操作。 - Ahmed Amr
@AhmedAmr 不能保证只创建一个Scanner对象,可以创建多个Reader对象,从而导致多个Scanner对象的存在。 - Swapnil Padaya

0
我看到许多人说重用扫描器是一个坏主意。为什么呢?
大多数情况下,重用扫描器对象并不是一个坏主意。没有更多的上下文,很难确定他们说这话的原因。可能是他们错了,也可能是您在重新使用时使用方式不正确而被他们指出。谁知道呢?
有一件事是肯定的:当您调用正在从System.in读取的对象中的Scanner#close()时,它也会关闭底层输入流。一旦输入流关闭,就无法在应用程序的生命周期内重新打开它。
难道如果重置扫描器就可以吗?
Scanner#reset()不是你想象的那样。实际上,在这个代码示例中,它什么也没做。此方法将Locale重置为US,并将基数重置回10进制。
代码分析
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
在某些情况下,重复使用Scanner是一个坏主意...因为已经被缓冲但未被Scanner消耗的数据会丢失。 - Stephen C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接