33

If I have a method that takes a reader and I want to operate on the reader with a Scanner like so:

Scanner scanner = new Scanner(reader);
while(scanner.hasNext()) {
    //blah blah blah
}

Is it safe not to close scanner? Documentation says that it "closes this scanner" and then talks about closing the underlying readable. Suppose I don't want to close the readable and instead want the caller to close reader when ready. Is it safe not to close scanner here?

tshepang
  • 10,772
  • 21
  • 84
  • 127
Anthony
  • 11,352
  • 9
  • 65
  • 100

4 Answers4

23

It depends what you want to be safe against.

  • If you are just trying to ensure that the underlying stream is closed, then either approach is fine.

  • If you also want the Scanner to be marked as closed (so that all subsequent operations on the object will fail immediately), then you should call Scanner.close().

This is a general principle; i.e. it also applies to various kinds of streams that do in-memory buffering, one way or another.

Stephen C
  • 632,615
  • 86
  • 730
  • 1,096
  • This answer matches the contract as defined in [the documentation](http://download.oracle.com/javase/6/docs/api/java/util/Scanner.html#close%28%29). – McDowell May 07 '11 at 08:41
9

Since I already have the source code open :-) ...

The close() method checks to see if the underlying Readable also implements the Closeable interface, and if it does it closes it. In your situation you are saying this is not a concern because it will be closed later.

But the close() method also sets some internal flags indicating that the Scanner (and underlying Readable) are closed. Many of the public methods first check to see if the Scanner has been closed. So the danger here would be that maybe your underlying Readable has been closed, but further calls to the Scanner don't immediately throw an IllegalStateException, and instead fail in some other way as they proceed.

If you can ensure that nothing else has a handle to the Scanner instance in question, and won't try to call any further methods on it, then you may be ok.

The close() method also nulls out its reference to the Readable, so if this doesn't happen the Scanner wouldn't get garbage collected as soon as it would have had you called close().

I'd call Scanner.close() if possible.

joergl
  • 2,842
  • 4
  • 34
  • 42
David
  • 1,451
  • 10
  • 18
1

I needed to close the Scanner as well, and keep the underlying stream open for further work. What I did is create a class that extends BufferedInputStream and overrides the close() method with an empty body. This class I fed into the constructor of the Scanner. This way, you can call scanner.close() without closing the stream. You need to keep a reference to the original BufferedInputStream though, but that is obvious.

wattostudios
  • 8,446
  • 13
  • 40
  • 54
Chris
  • 11
  • 1
0

Well, if you have Caller and Reader class. Caller shouldn't know about the implementation of Reader. In reader's next method:

while scanner has object
   read them ( one object per method's call) 
when objects are done
   close the reader. 

This is a kind of iterator pattern.

StKiller
  • 6,955
  • 8
  • 39
  • 56