Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

When Might Scanner.findInLine Block?  RSS feed

 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The javadoc on Scanner.findInLine says this about it:

Attempts to find the next occurrence of the specified pattern ignoring delimiters. If the pattern is found before the next line separator, the scanner advances past the input that matched and returns the string that matched the pattern. If no such pattern is detected in the input up to the next line separator, then null is returned and the scanner's position is unchanged. This method may block waiting for input that matches the pattern.


I'm using that to search a file for a pattern in this loop:



Am I correct in assuming that nextLine will always supply a line separator? If so, when could findInLine block? Is there another way to provide data to findInLine, maybe some partial line that neither includes a matching string and also does not end in a line separator?
 
Paul Clapham
Sheriff
Posts: 22476
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your javadoc quote implies that the method will return either when the pattern is found or when the next line separator is found. When you're reading from a file then the blocking will be trivially small, but if you were reading from a socket connection you might find that waiting for the next line separator blocks because the person at the other end of the connection hasn't pressed the Enter key yet, or some other network-related delay is taking place.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm sure this is because I'm ignorant about the Scanner class, but I thought the reading took place in Scanner.nextLine, and Scanner.findInLine merely operated on what Scanner.nextLine had read. I could see how that would mean Scanner.nextLine could block, but not how Scanner.findInLine could block.What am I missing?
 
Paul Clapham
Sheriff
Posts: 22476
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The javadoc you quoted does seem to me to be saying that it reads ahead, and if it reaches the line ending without matching the pattern then "the scanner's position is unchanged". In other words the data it read through while failing to match the pattern is put back into the buffer for future reading.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Seems that it does do some reading. If its internal needInput flag is set, it calls this:



I'm very surprised. If Scanner.findInLine reads, what's Scanner.nextLine for?
 
Paul Clapham
Sheriff
Posts: 22476
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What's Scanner.nextLine() for? The docs say:

Advances this scanner past the current line and returns the input that was skipped.


I think your problem is that you believe that findInLine() actually consumes the data up to the next line-end if it doesn't match the pattern. If you try believing that findInLine() looks forward speculatively as far as the next line-end and then rolls back to where it started if it doesn't match the pattern, you won't have as much cognitive dissonance.

Now I worked with Java for years before they wrote Scanner, so for me Scanner is an excessively complicated beast which doesn't add any value to Java as far as I'm concerned. Besides which I almost never had to write code to extract things from loosely-formatted text, so again it had no value for me. So in practice I know basically nothing about Scanner. However I think you'll find my reading of the docs in this case doesn't lead to any contradictions.

By the way it looks like all of the "hasXXX" methods do speculative reading as well, but their docs all say

The scanner does not advance past any input.


If you think about it, hasNextFloat (for example) would have to look forward to see if the next token matches a float, but it shouldn't actually consume that float.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:I think your problem is that you believe that findInLine() actually consumes the data up to the next line-end if it doesn't match the pattern. If you try believing that findInLine() looks forward speculatively as far as the next line-end and then rolls back to where it started if it doesn't match the pattern, you won't have as much cognitive dissonance.


But what's it do after that roll-back? I know for a fact that it doesn't just block, because I have fed it files that:

  • Have more than one line-end.
  • Contain nothing that matches the pattern.
  • Do not cause it to block.


  • From the code, it appears that it actually reads more data. Okay, and, as you say, if that data is coming from a stream that might neither have more data ready, nor signal that it is closed, it might block. But, still, I ask: what's Scanner.nextLine do? I thought it read the next line, which then became available for Scanner.findInLine to examine. Clearly, I am wrong about that. Scanner.findInLine can read its own data. So what's Scanner.nextLine do?

    Now I worked with Java for years before they wrote Scanner, so for me Scanner is an excessively complicated beast which doesn't add any value to Java as far as I'm concerned.

    You have me convinced. What else can I use to look for a regex pattern in a stream? Whatever it is, it must be interruptible.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!