views:

206

answers:

2

I am using java.util.Scanner for things such as nextInt(), and all was working fine as long as I was using a java.lang.Readable (one and only constructor argument). However, when I changed to using an InputStream instead, Scanner.nextInt() never returns. Do you know why?

My implementation of the InputStream looks like this:

private static class ConsoleInputStream extends InputStream {
    ...
    private byte[] buffer;
    private int bufferIndex;
    public int read() throws IOException {
        ...
        while (...) {
            if (buffer != null && bufferIndex < buffer.length) {
                return buffer[bufferIndex++];    // THE COMMENT!
            }
            ...
        }
        ...
    }
}

When I print the data by THE COMMENT I (correctly) get stuff like '1','2','\n' for "12\n", etc. Is there some Scanner hookup, unbeknown to me, that cause this behavior?

+3  A: 

From the javadocs for InputStream's read() method:

"Returns: the next byte of data, or -1 if the end of the stream is reached."

I would guess that you're never returning -1?

Rob Oxspring
I figured that meant "permanent" end of the stream (as in "don't read me any more"), not just a "delimiter" (as in a line feed).
Jonas Byström
Normally, that -1 is the end of the show. I'm not sure how consumers of the stream would react if the stream suddenly changed its mind.
Carl Smotricz
Thought I saw that somewhere too. (But now it's working so I'll just move on with my "never trust documentation"-attitude. :)
Jonas Byström
@Jonas - you don't have to trust the documentation. You can read the source code of the Java class libraries!
Stephen C
My point exactly! ;)
Jonas Byström
+1  A: 

I think the problem is with your self-built InputStream. Why did you build your own, rather than simply simply using System.in ?

Update:

Wanted input from a JTextField.

OK, got it. It usually doesn't make sense to use I/O handling to read stuff that's already available, in character form, but I can see how that would make your life easier with Scanner.

Still, you could probably have saved yourself some coding and grief by using a "finished" InputStream. What comes to mind is

InputStream is = new ByteArrayInputStream(myTextField.getText().getBytes());

Java I/O is yucky. Be glad the bright people from Sun have encapsulated most of it away for you.

Carl Smotricz
Wanted input from a JTextField.
Jonas Byström
Sounds sensible, although I needed to give the users of my jar both static (persistent) InputStreams and Scanners.
Jonas Byström
I hear you. But I want to instill a really guilty conscience in you for using essentially undefined behavior. It is not a good idea for an input stream to change its mind about whether it's at EOF, and your code may fail on a future JVM and you'll spend a lot of time cursing yourself as you debug.
Carl Smotricz
I bet it's an undocumented feature; and to such degree that change would cause havoc among millions of users.
Jonas Byström
No, I don't think it's that kind of feature. It looks more like an oversight. I honestly believe that what you are doing is VERY unusual and thus unlikely to be protected by historic precedent. But I'm going to give up now ;)
Carl Smotricz