41

I have a Scanner linked to System.in. Now, after using the Scanner, I should close it, as it is bad coding practice to leave it open. But, if I close the Scanner, I will also be closing System.in! Can anyone tell me how I can close the Scanner without closing System.in (if there is any way).

JavaNewbie_M107
  • 1,897
  • 3
  • 19
  • 32
  • http://stackoverflow.com/questions/5919143/is-it-safe-not-to-close-a-java-scanner-provided-i-close-the-underlying-readable hopefully this can be of use to you. Im still looking to see if System.in implements closeable. If not, they you're in the clear. – paul jerman Jan 03 '13 at 16:25
  • 4
    Note that you can guard the stream with a [decorator](http://commons.apache.org/io/api-release/org/apache/commons/io/input/CloseShieldInputStream.html). – McDowell Jan 03 '13 at 16:28
  • Yep, System.in does implement closeable. – JavaNewbie_M107 Jan 03 '13 at 16:28
  • @pauljerman `System.in` is a `InputStream` and therefore implements `AutoClosable`, see [the docs](http://docs.oracle.com/javase/7/docs/api/java/lang/System.html). – jlordo Jan 03 '13 at 16:29
  • scratch that, don't close you're scanner. I'll post the answer – paul jerman Jan 03 '13 at 16:29
  • @McDowell sorry about hijacking your answer. Didn't see it until I had already posted the same thing XD – paul jerman Jan 03 '13 at 16:37
  • @pauljerman - not an issue – McDowell Jan 03 '13 at 16:49
  • possible duplicate of [Closing BufferedReader and System.in](http://stackoverflow.com/questions/8203981/closing-bufferedreader-and-system-in) – Raedwald Jun 22 '15 at 11:32
  • 2
    *"Doctor, it hurts when I do this!" ... "Don't do that, then."* – kaya3 Mar 02 '20 at 22:16

5 Answers5

28

The simplest thing is to not close Scanner if you don't want to close the underlying stream.

Ideally you should create just one Scanner which you use for the life of the program. In any case, it appears you don't have a good reason to close it.

Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
  • 4
    This works by requiring code to KNOW it's talking to system in, or at least something that shouldn't be closed. Paul Jermans recommendation of `CloseShieldInputStream` allows the code to ignore that fact and simply treat it like any other InputStream and attempt to close it when finished. What is simple here really depends on context. – candied_orange Nov 26 '16 at 18:07
  • @candied_orange you shouldn't be closing a stream that you don't own (which, given the lack of a strong notion of ownership in Java, roughly means that you didn't *open*). If you got the stream from somewhere else, don't close the Scanner. – Andy Turner Oct 12 '18 at 06:55
  • @AndyTurner that works. If you want to follow that rule and still have freedom to use widely look up the [hole in the middle pattern](https://www.google.com/amp/s/jbergmanster.wordpress.com/2007/09/12/a-simple-example-of-the-hole-in-the-middle-pattern/amp/) – candied_orange Oct 12 '18 at 13:43
25

One option is to wrap your System.in stream in a CloseShieldInputStream that prevents it from being closed. Your reader would then use the CloseShieldInputStream rather than the raw System.in stream.

Here is the API for the class: http://commons.apache.org/io/apidocs/org/apache/commons/io/input/CloseShieldInputStream.html

Tiny
  • 24,933
  • 92
  • 299
  • 571
paul jerman
  • 553
  • 4
  • 13
10

Instead of adding shield classes and stuff like that, just put a nice comment and a

        @SuppressWarnings("resource")

That's good enough. And I don't seem to see a lot of drawbacks to this approach. Don't forget the comment.

mist
  • 1,835
  • 2
  • 19
  • 33
  • ? This might supress a warning but doesn't prevent you from getting an `IOException: Stream closed` when trying to use the `System.in` after closing the Scanner – derHugo Dec 14 '18 at 13:38
  • 3
    @derHugo I think they mean **don't** close the Scanner and suppress the warnings about *that* with an annotation and add an explaining comment. – bkis Jan 15 '19 at 13:54
0

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

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.

Blrp
  • 1,131
  • 3
  • 14
  • 34
  • 1
    You're just avoiding the warning by confusing Eclipse code analysis here :) The scanner is still never closed (not that you should :)) – john16384 Feb 28 '17 at 08:44
-8

According to the API for InputSteam "The close method of InputStream does nothing.", so since System.in is an instance of InputStream, you don't need to worry about close() being called on it.

Ted McLeod
  • 13
  • 1
  • 2
    Clearly that's not the case though. If I open a `Scanner` on `System.in`, close it, and then open another and then try to use it (e.g. `nextLine()`), I get `NoSuchElementException`. – Blrp Nov 06 '15 at 18:17
  • 6
    While `close()` indeed does nothing in the default implementation of the abstract `InputStream`, that doesn't mean this is true for all of its subclasses! If that was true, the method would be useless. – Jiri Tousek Jan 08 '16 at 16:27
  • 2
    `InputStream` is an abstract class. Subclasses can and should "do something" when they represent a resource (such as stdin) that needs to be closed after use. Granted that could be made clearer in `InputStream.close()`, but your conclusion is incorrect. – dimo414 Feb 26 '16 at 18:51
  • This answer is totally wrong, and I think it need to be deleted – aristotll Sep 16 '20 at 03:13