关闭链接到 System.in 的扫描仪

Close a Scanner linked to System.in

提问人:JavaNewbie_M107 提问时间:1/4/2013 更新时间:11/18/2015 访问量:21148

问:

我有一个链接到.现在,在使用 之后,我应该关闭它,因为让它保持打开状态是不好的编码实践。但是,如果我关闭 ,我也会关闭!谁能告诉我如何在不关闭的情况下关闭(如果有办法)。ScannerSystem.inScannerScannerSystem.inScannerSystem.in

java.util.scanner

评论

0赞 paul jerman 1/4/2013
stackoverflow.com/questions/5919143/......希望这对你有用。我仍在寻找 System.in 实现是否可关闭。如果没有,他们就很清楚了。
4赞 McDowell 1/4/2013
请注意,您可以使用装饰器保护流。
0赞 JavaNewbie_M107 1/4/2013
是的,System.in 确实实现了可关闭。
0赞 jlordo 1/4/2013
@pauljerman 是 ,因此实现 ,请参阅文档System.inInputStreamAutoClosable
5赞 kaya3 3/3/2020
“医生,我这样做很痛!”“那就别那样做。”

答:

30赞 Peter Lawrey 1/4/2013 #1

最简单的方法是,如果您不想关闭底层流,请不要关闭 Scanner。

理想情况下,您应该只创建一个扫描仪,并在程序的整个生命周期内使用。无论如何,您似乎没有充分的理由关闭它。

评论

4赞 candied_orange 11/27/2016
这通过要求代码知道它正在与系统通信,或者至少是不应该关闭的东西来工作。Paul Jermans 的建议允许代码忽略这一事实,并简单地将其视为任何其他 InputStream,并在完成后尝试关闭它。这里的简单之处实际上取决于上下文。CloseShieldInputStream
2赞 Andy Turner 10/12/2018
@candied_orange你不应该关闭一个你不拥有的流(鉴于 Java 中缺乏强烈的所有权概念,这大致意味着你没有打开)。如果您从其他地方获取了流,请不要关闭扫描仪。
0赞 candied_orange 10/12/2018
@AndyTurner有效。如果你想遵循这个规则,并且仍然可以自由地广泛使用,请查找中间模式中的孔
27赞 paul jerman 1/4/2013 #2

一种选择是将流包装在防止其关闭的 a 中。然后,您的读者将使用 而不是原始流。System.inCloseShieldInputStreamCloseShieldInputStreamSystem.in

下面是该类的 API:http://commons.apache.org/io/apidocs/org/apache/commons/io/input/CloseShieldInputStream.html

评论

0赞 paul jerman 1/4/2013
您还可以为 System.in 流创建自己的自定义不可关闭包装器
10赞 mist 7/6/2014 #3

与其添加盾牌类和类似的东西,不如放一个漂亮的评论和一个

        @SuppressWarnings("resource")

这已经足够好了。而且我似乎没有看到这种方法有很多缺点。不要忘记评论。

评论

1赞 derHugo 12/14/2018
?这可能会抑制警告,但不会阻止您在关闭扫描仪后尝试使用警告IOException: Stream closedSystem.in
6赞 bkis 1/15/2019
@derHugo我认为他们的意思是不要关闭扫描仪并用注释抑制有关的警告,并添加解释性注释。
-11赞 Ted McLeod 11/6/2015 #4

根据 InputSteam 的 API “InputStream 的 close 方法不做任何事情”,因此由于 System.in 是 InputStream 的实例,因此您无需担心 close() 被调用。

评论

2赞 H.v.M. 11/7/2015
但显然情况并非如此。如果我打开一个 打开,关闭它,然后打开另一个,然后尝试使用它(例如),我得到 .ScannerSystem.innextLine()NoSuchElementException
7赞 Jiri Tousek 1/9/2016
虽然在抽象的默认实现中确实没有做任何事情,但这并不意味着它的所有子类都是如此!如果这是真的,那么这种方法将毫无用处。close()InputStream
3赞 dimo414 2/27/2016
InputStream是一个抽象类。当子类表示使用后需要关闭的资源(例如 stdin)时,它们可以而且应该“做某事”。当然,这可以在 中更清楚,但你的结论是不正确的。InputStream.close()
2赞 aristotll 9/16/2020
这个答案是完全错误的,我认为需要删除
0赞 Erwin 4/9/2023
如果我们看到 InputStream 的其他方法,比如 mark,它也说 InputStream 的 mark 方法什么都不做。但是,如果我们看到 reset 方法,它会说 InputStream 类的 reset 方法除了抛出 IOException 之外什么都不做。所以上面的句子 about 没有任何作用,例如抛出一个异常
0赞 H.v.M. 11/7/2015 #5

I have vague memories of strange, undiagnosable problems long ago with using the same of twice, so this is what I use (even though you should probably just use one scanner for the duration of the program):ScannerSystem.in

static String input() {
    try {
        return new Scanner(System.in).nextLine();
    } catch (NoSuchElementException e) {
        throw e;
    }
}

For some reason this works without warnings, whereas if I don't do the catch-throw, Eclipse will complain .Resource leak: '<unassigned Closeable value>' is never closed

评论

1赞 john16384 2/28/2017
You're just avoiding the warning by confusing Eclipse code analysis here :) The scanner is still never closed (not that you should :))