Java Scanner next() method - java

This is from the Java's Scanner next() method explanation:
This method may block while waiting for input to scan, even if a
previous invocation of hasNext() returned true.
How can this method wait for user input to be entered if a call to hasNext() is made? If we call hasNext() and it returns true, we know that there is next token, so how and why the next() method does this?

You need to read the full documentation of the method:
Finds and returns the next complete token from this scanner. A
complete token is preceded and followed by input that matches the
delimiter pattern. This method may block while waiting for input to
scan, even if a previous invocation of hasNext() returned true.
The Scanner#hasNext method (documentation) may return true when there is another token. But it could be possible that the token is not yet considered as complete according to the delimiter pattern and Scanner#next will always block until the the token is complete.
If there is a complete token in the Scanner then Scanner#next will immediately return and not block.
You can set the delimiter pattern by using the Scanner#useDelimiter method (documentation)
If you don't set a specific delimiter pattern than the Scanner will use a default pattern which matches whitespace characters.
As you have asked, blocked means that the method waits and does not return until the said event happened.
Consider this:
System.out.println("Before");
someBlockingMethod();
System.out.println("After");
With
public void someBlockingMethod() {
// Sleep for a second (ignoring exceptions for simplicity)
Thread.sleep(1000);
}
You will see After only once someBlockingMethod() has returned and this will only happen once the said event occurred. Thus the method blocks. In the example the method blocks for one second.

Scanner#next doesn't return a string until it has either reached the delimiter being used by the Scanner (whitespace is the default delimiter), or it has reached the end of the input stream.
If hasNext returns true, it means there is definitely more data in the input stream, but it may still need to block until it reaches the delimiter/EOF.

If you debug the following code, you will see that, actually, it is hasNext() method that is blocking and waiting for user input:
Scanner scanner = new Scanner(System.in);
if (scanner.hasNext()) {
String s = scanner.next();
}
That's because there is a blocking step inside hasNext():
public boolean hasNext() {
ensureOpen();
saveState();
while (!sourceClosed) {
if (hasTokenInBuffer())
return revertState(true);
readInput(); //THIS IS WAITING FOR USER INPUT
}
...
In case of console input, hasNext() waits till a complete token is entered and returns true, then subsequent next() invocation doesn't block.
In case of non-console input, hasNext() returns true even if there is not complete token, and subsequent next() invocation blocks and waits for complete token.

Related

Explanation for Java (palindrom string) and method next();

I want to know more about how next method work and Java utill scanner if someone can help me...
Scanner s = new Scanner(System.in);
System.out.println("Unesite string za proveru: ");
if(palindrom(s.next()))
System.out.println("String je palindrom");
else
System.out.println("String nije palindrom");
s.close();
what does next do? and how exactly scanner working also what means method close(); ??
next
public String next()
Finds and returns the next complete token from this scanner.A complete token is preceded and followed by input that matchesthe delimiter pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.
Specified by:next in interface IteratorReturns:the next tokenThrows:NoSuchElementException
1 - if no more tokens are availableIllegalStateException
2- if this scanner is closedSee Also:Iterator
example :-
sc = "hello world"
1st time sc.next() output will be "hello"
2nd time sc.next() output will be "world"
close
public void close()
Closes this scanner.
If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close methodwill be invoked. If this scanner is already closed then invoking thismethod will have no effect.
Attempting to perform search operations after a scanner hasbeen closed will result in an IllegalStateException.
Specified by:close in interface CloseableSpecified by:close in interface AutoCloseable
Scanner is a class that parses, and in some cases converts inputs. It uses whitespace as its default delimiter between tokens.
Scanner.next is a method that finds and returns the next token, if there is one.
Scanner.close is a method that releases the resource that the Scanner object is holding, such as an open file.

Checking hasNextInt() in if and then receive an input

So a simple program would be:
import java.util.*;
public class practice {
static Scanner reader = new Scanner(System.in);
public static void main(String[] args) {
if(reader.hasNextInt()){
int numberEntered = reader.nextInt();
}
}
}
So I have a misunderstanding. hasNextInt() is supposed to check if the next input will be an int or not. I saw this program and I don't understand how the number can be inputed. Because already for getting an input the reader.hasNextInt() needs to be true and the program hasn't got an input. So how will the program get inside the if statement?
The method Scanner#hasNextInt(), in your case, is a blocking method. This means, it is a method which waits and does only return if some conditions are met. It looks something like this:
public boolean hasNextInt() {
...
boolean condition = false;
while(!condition) {
...
}
...
return stuff;
}
To be more precise, the blocking method is Scanner#hasNext(). It is described in its documentation.
If the method blocks or not depends on the Scanners source. If it is, for example System.in, it will wait. If it is just a File, it will read the whole file until its end and then return, no blocking.
So, what happens? The hasNextInt in your if-condition waits for you to enter some input (until you send it by typing Enter). Then the Scanner saves the input inside a buffer. hasNextInt checks the internal buffer but does not delete stuff from the buffer.
Now comes nextInt which reads from the internal buffer and also deletes the stuff inside it. It advances past read input.
You can read it in detail inside the documentation mentioned above.
Things short: Scanner#hasNextInt() waits for input before it returns true or false.

How input was taken just using object of Scanner class?

public class Two {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int c=0;
while(sc.hasNext())System.out.println(++c+" "+sc.nextLine());
}
}
I came across this code and i want to confirm that by taking input directly without using object of any datatype all we are doing is taking input and displaying it and we are not storing it anywhere?
and also how is the condition inside while loop is true for the first time? As we have not given any input yet.
Sure, your code doesn't store sc.nextLine() , so this value will be discarded past the System.out.println instruction.
Also for hasNext() :
This method may block while waiting for input to scan.
so the condition will be met once the stream begins to provide input, and the method will block waiting for this to happen or an Exception to happen (e.g : if the Scanner gets closed ).
As long as nothing of those things happen, hasNext() method doesn't return, so the condition in while is still not evaluated, so the loop is blocked there .
Let's go through your code:
Scanner sc = new Scanner(System.in)
The java.util.Scanner.Scanner(InputStream) constructor is called, and you have an object sc of type Scanner which reads from System.in.
int c = 0;
You now have a primitive c of primitive type int.
while(sc.hasNext()) { ... }
The while loop evaluates sc.hasNext(), which is true. As per the documentation, sc.hasNext() returns true if and only if the input has another token in it. In your case, this means that the InputStream is open.
{... System.out.println(++c + " " + sc.nextLine()); ...}
sc.nextLine() is the problem. Assuming you have not changed System.in, the console/terminal will block the loop (i.e. hold the loop paused) until you give it an input (type in some text and hit [ENTER]).
So, overall:
Scanner::hasNext() will return true if and only if it is possible to get more input (if you are using System.in, this will always be true until you close the scanner).
If you are printing the input directly, you will not be storing any references to it, and no memory will be allocated for it (unless Scanner.nextLine() stores it somewhere).

Scanner next() confusion

In class java.util.Scanner,method public String next() finds and returns the next complete token from this Scanner,I am confused,if I write a program like this:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println(in.next());
in.close();
}
and run this program,then input a word and the word will be printed,it seems that method next() returns the current token,why does the API say next() returns the next complete token?
I will describe what all of this is about, since you are confused.
Scanner input = new Scanner(System.in)
java.lang.System is a public final class extending java.lang.Object and it has static fields namely err and out being of type PrintStream and in being of type InputStream hence,
System.in
java.util.Scanner extends java.lang.Object and implements the following interfaces:
Iterator
Closeable
AutoCloseable
Now that we understood the hierarchy. What happens during execution?
Execution of > Scanner input = new Scanner(System.in)
Constructs a new Scanner object passing it the source through which it should expect the input.
Execution of > input.next()
does the following steps
Block execution while waiting for input to scan
As soon as you provide an input (assume below)
"Hello World! This is a test."
and hit Enter the following steps take place
Scanner read the data from Input Stream
Tokenizes the input using the delimiter (default whitespace)
Construct an iterator similiar to Iterator iterate = tokens.iterator() for iteration through tokens
Find the first complete token being "Hello" in the scanner, returns the token and waits before next token.
The reason the first complete token is returned is because that is how next() method that is inherited from java.util.Iterator behaves. Basically think of it a pointer pointing to bunch of tokens in scanner arranged in an order. As soon as next() is invoked, returns first token and moves the pointer ahead.
hasNext() on the other hand, returns true if this scanner has another token from the location the iterator is pointing to. Unlike next() it does not advance past the token.
The documentation says the following about next()
Finds and returns the next complete token from this scanner. A
complete token is preceded and followed by input that matches the
delimiter pattern. This method may block while waiting for input to
scan, even if a previous invocation of hasNext() returned true.
This is because you assigned the Scanner to standart input (System.in).
If you use your exact program in this
IDEONE DEMO
OUTPUT (check in the link how stdin is assigned prior to execute)
Success!
stdin // this is what you assign
hello word
stdout // this is the output of main method
hello
word
If this does not clarify, maybe you will find this example useful. Check how I assign the Scanner to a created String:
String input = "hello my name is Jordi";
Scanner s = new Scanner(input); // assign the scanner to String s!!!!
System.out.println(s.next()); // prints: hello
System.out.println(s.next()); // prints: my
System.out.println(s.next()); // prints: name
System.out.println(s.next()); // prints: is
System.out.println(s.next()); // prints: Jordi
s.close();
You can think, that initially Scanner point on the beginning of the string, then when you call next() it reads starts from the current position.
Like this:
[h][e][l][l][o][_]
^
Scanner behave similar to iterators and starts "before" first character.

Why does hasNextLine() never end?

Sorry if this sounds too simple. I'm very new to Java.
Here is some simple code I was using to examine hasNextLine(). When I run it, I can't make it stop. I thought if you didn't write any input and pressed Enter, you would escape the while loop.
Can someone explain to me how hasNextLine() works in this situation?
import java.util.*;
public class StringRaw {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
String str = sc.nextLine();
}
System.out.print("YOU'VE GOT THROUGH");
}
}
When reading from System.in, you are reading from the keyboard, by default, and that is an infinite input stream... it has as many lines as the user cares to type. I think sending the control sequence for EOF might work, such as CTL-Z (or is it CTL-D?).
Looking at my good-ol' ASCII chart... CTL-C is an ETX and CTL-D is an EOT; either of those should work to terminate a text stream. CTL-Z is a SUB which should not work (but it might, since controls are historically interpreted highly subjectively).
CTRL-D is the end of character or byte stream for UNIX/Linux and CTRL-Z is the end of character or byte stream for Windows (a historical artifact from the earliest days of Microsoft DOS).
With the question code as written, an empty line won't exit the loop because hasNextLine() won't evaluate to false. It will have a line terminator in the input byte stream.
System.in is a byte stream from standard input, normally the console. Ending the byte stream will therefore stop the loop. Although nextLine() doesn't block waiting for input, hasNextLine() does. The only way the code terminates, as designed, is with CTRL-Z in Windows or CTRL-D in UNIX/Linux, which ends the byte stream, causes hasNextLine() not to block waiting for input and to return a boolean false which terminates the while loop.
If you want it to terminate with an empty line input you can check for non-empty lines as part of the loop continuation condition. The following code demonstrates how to change the basic question design that uses hasNextLine() and nextLine() to one that terminates if it gets an empty line or an end of input character (i.e. CTRL-Z in Windows or CTRL-D in UNIX/Linux). The additional code in the while condition uses a feature of assignment operators wherein they can be evaluated like an expression to return the value that was assigned. Since it is a String object, the String.equals() method can be used with the evaluation.
Other additional code just adds some printed output to make what is going on obvious.
// HasNextLineEndDemo.java
import java.util.*;
public class HasNextLineEndDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// this code is a bit gee-whiz
// the assignment expression gets assigned sc.nextLine()
// only if there is one because of the &&
// if hasNextLine() is false, everything after the &&
// gets ignored
// in addition, the assignment operator itself, if
// executed, returns, just like a method return,
// whatever was assigned to str which,
// as a String object, can be tested to see if it is empty
// using the String.equals() method
int i = 1; // input line counter
String str = " "; // have to seed this to other than ""
System.out.printf("Input line %d: ", i); // prompt user
while (sc.hasNextLine() && !(str = sc.nextLine()).equals("")) {
System.out.printf("Line %d: ", i);
System.out.println("'" + str + "'");
System.out.printf("Input line %d: ", ++i);
} // end while
System.out.println("\nYOU'VE GOT THROUGH");
} // end main
} // end class HasNextLineEndDemo
Hit Ctrl + D to terminate input from stdin. (Windows: Ctrl + Z) or provide input from a command:
echo -e "abc\ndef" | java Program
I had a similar problem with a socket input stream. Most solutions I found would still block the execution. It turns out there is a not-blocking check you can do with InputStream.available().
So in this case the following should work:
int x = System.in.available();
if (x!=0) {
//Your code
}
As per my understanding , if you take an example of result set object from JDBC or any iterator then in these cases you have a finite set of things and the iterators each time check whether end of the set has been reached.
However in the above case , their is no way of knowing the end of user input i.e. hasNextLine() has no way of knowing when user wants to terminate, and hence it goes on infinitely.
Best way is to put additional condition on the for loop that checks for some condition inside for loop that fails in the future.
In the above post #Jim 's answer illustrates this.
In fact using hasNextLine() as loop terminator for console input should be discouraged because it will never return false.

Categories

Resources