Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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");
    }
}
like image 755
Helgi Avatar asked Apr 13 '11 17:04

Helgi


People also ask

What does hasNextLine () do in Java?

The hasNextLine() method checks to see if there's another line in the input of the Scanner object, no matter if the line is blank or not.

How do I cancel hasNext?

The only way you can get hasNext() to return false is by terminating the input. In the case of file input, that means you have passed the last line. OTOH the input from System.in will continue until you terminate it with ctrd‑D (on Macs or *nix) or ctrl‑Z (Windows®). That closes System.in and you cannot reopen it.

What is the return type for the hasNextLine method in the scanner class?

The hasNextLine() method of java. util. Scanner class returns true if there is another line in the input of this scanner. This method may block while waiting for input.


2 Answers

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).

like image 59
Lawrence Dol Avatar answered Sep 20 '22 05:09

Lawrence Dol


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
like image 26
Jim Avatar answered Sep 20 '22 05:09

Jim