Scanner.hasNextLine - always true - java

I need to read data from standard input.
And I want to print it to standard output.
I use Scanner for this:
import java.util.Scanner;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
int countLines = 1;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
sb.append(countLines).append(" ").append(line);
}
System.out.println("finish");
System.out.println(sb.toString());
scanner.close();
}
I input this data:
Hello world
I am a file
Read me until end-of-file.
But hasNextLine()) is always true. And as result never print "finish"

Your code seems to work fine. Are you sure you output EOF correctly? Try Ctrl+D (Cmd+D on Mac) or Ctrl+Z on Windows, as mentioned here: How to send EOF via Windows terminal

There is no condition in which the loop will be false, it'll read the lines forever and ever. Consider adding a stop keyword like "stop"
while(scanner.hasNextLine())
{
String line = scanner.nextLine();
if(line.equalsIgnoreCase("stop"))
{
break;
}
//whatever else you have in the loop
}
Unless you stop it, it'll always be true. As pointed out by #Aaron
Scanner.hasNextLine() blocks waiting for a new line, it will only return false if you close the stream (using Ctrl-Z or D as Liel mentions in his answer)

Related

Java display file line by line using Enter key

I'm trying to progress displaying a file line by line with an Enter key, but the if statement that I try doesn't seem to work. If I disregard the if statement, it works, but it feels incomplete because then I'm asking for input and doing nothing with it.
This is what I have:
import java.util.Scanner;
import java.io.*;
public class LineByLine {
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(System.in);
System.out.println("What is the filename?");
String input = in.nextLine();
BufferedReader buff = new BufferedReader(new FileReader(input));
String sen = buff.readLine();
System.out.println(sen);
Scanner enter = new Scanner(System.in);
while (sen != null){
String output = enter.next();
if (output.equals("")){
System.out.println(sen = buff.readLine());
}
}
}
}
I just don't know why my if statement doesn't work.
The core issue is that you misunderstand Scanner and its default configuration: Out of the box, scanner splits on any amount of whitespace. .next() asks for the next token; a token is the thing that appears in between the whitespace.
Thus, pressing enter 500 times produces zero tokens. After all, tokens are what's in between the separator, and the default separator is 'any amount of whitespace'. Pressing enter a bunch of time is still just you entering the same separator.
The underlying problem is that most people appear to assume that Scanner reads one line at a time. It doesn't do that. At all. But you want it to. So, tell it to! Easy peasy - make scanner do what you already thought it did:
Scanner in = new Scanner(System.in);
in.useDelimiter("\\R"); // a single enter press is now the separator.
You should also stop using nextLine on scanners. nextLine and any other next call do not mix. The easiest way to solve this problem is to only ever use nextLine and nothing else, or, never use nextLine. With the above setup, .next() gets you a token which is an entire line - thus, no need for nextLine, which is good news, as nextLine is broken (it does what the spec says it should, but what it does is counterintuitive. We can debate semantics on whether 'broken' is a fair description of it. Point is, it doesn't do what you think it does).
Also, while you're at it, don't make multiple scanners. And, to improve this code, resources must be properly closed. You're not doing that. Let's use try-with, that's what it is for.
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(System.in);
in.useDelimiter("\\R");
System.out.println("What is the filename?");
String input = in.next();
try (BufferedReader buff = new BufferedReader(new FileReader(input))) {
String sen = buff.readLine();
System.out.println(sen);
while (sen != null){
enter.next(); // why does it matter _what_ they entered?
// as long as they pressed it, we're good, right? Just ignore what it returns.
System.out.println(sen = buff.readLine());
}
}
}

How do I read both from keyboard and from file?

I have a Scanner that could be reading from either keyboard or from a file (via pipes), and apparently there's no way to tell which.
I have te following code:
Scanner scan = new Scanner(System.in);
while (scan.hasNextLine()) {
String line = scan.nextLine();
doStuff();
}
That works wonderfully when redirecting input to a file. But if I try to run the program by itself and read from keyboard, it enters an infinite loop. Is there a way to differentiate between reading from keyboard and from a file? Thanks in advance!
Edit 1:
As requested by #Abra, this is what my code looks like with your suggestion:
Scanner scan = new Scanner(System.in);
do {
String linea = scan.nextLine();
doStuff();
} while (System.in.available() != 0 && scan.hasNextLine());
And here's the command I'm running:
java -jar Class.jar < File.txt
Edit 2:
Solved it, turns out I should only evaluate System.in.available() != 0 once:
Scanner scan = new Scanner(System.in);
boolean file = System.in.available() != 0;
do {
String linea = scan.nextLine();
doStuff();
} while (file && scan.hasNextLine());
The classic practice used commonly in Linux and Unix is to read input from standard input, as you are already doing. In Java, standard input is called System.in.
The program reads from standard input and processes what it reads in a loop until it detects end-of-file, which you are already doing.
So your program is not stuck - it is merely waiting for more input or for the end-of-file signal to come from the outside.
If you want to use this program with input from a file, you run it like this:
myprogram < input_file.txt
And if you want your program to get its input from terminal (where you type it), you run it just like
myprogram
In this case, and after typing your input, you are also responsible to send a special signal from your terminal that will act as a "end-of-file" and will be picked by the program, causing the while-loop to exit. Typically, you do this by pressing Control-D.
Keep in mind that reading from standard input is not strictly the same as reading from keyboard. Standard input only knows about text and end-of-file; it has no concept of line editing, testing for when shift key is pressed/released etc.
The class of System.in is java.io.InputStream. That class has method available(). If you redirect System.in to a file, as in
myprogram < input_file.txt
Then method available() returns a number greater than zero (assuming that input_file.txt has non-zero size) but when System.in refers to the standard input stream, i.e. when you run your program without redirecting standard input, as in
myprogram
Then method available() returns zero.
based on the answer of #Abra you can break the loop if System.in is keyboard so:
import java.util.Scanner;
import java.io.IOException;
public class Main {
public static void main(String[] argv) throws IOException {
Scanner scan = new Scanner(System.in);
boolean isKeyboard = System.in.available() == 0;
while (scan.hasNextLine()) {
String line = scan.nextLine();
doStuff();
if (isKeyboard) {
break;
}
}
}
}

Scanner.next() and hasNext() creating infinite loop when reading from console [duplicate]

I ran into an issue. Below is my code, which asks user for input and prints out what the user inputs one word at a time.
The problem is that the program never ends, and from my limited understanding, it seem to get stuck inside the while loop. Could anyone help me a little?
import java.util.Scanner;
public class Test{
public static void main(String args[]){
System.out.print("Enter your sentence: ");
Scanner sc = new Scanner (System.in);
while (sc.hasNext() == true ) {
String s1 = sc.next();
System.out.println(s1);
}
System.out.println("The loop has been ended"); // This somehow never get printed.
}
}
You keep on getting new a new string and continue the loop if it's not empty. Simply insert a control in the loop for an exit string.
while(!s1.equals("exit") && sc.hasNext()) {
// operate
}
If you want to declare the string inside the loop and not to do the operations in the loop body if the string is "exit":
while(sc.hasNext()) {
String s1 = sc.next();
if(s1.equals("exit")) {
break;
}
//operate
}
The Scanner will continue to read until it finds an "end of file" condition.
As you're reading from stdin, that'll either be when you send an EOF character (usually ^d on Unix), or at the end of the file if you use < style redirection.
When you use scanner, as mentioned by Alnitak, you only get 'false' for hasNext() when you have a EOF character, basically... You cannot easily send and EOF character using the keyboard, therefore in situations like this, it's common to have a special character or word which you can send to stop execution, for example:
String s1 = sc.next();
if (s1.equals("exit")) {
break;
}
Break will get you out of the loop.
Your condition is right (though you should drop the == true). What is happening is that the scanner will keep going until it reaches the end of the input. Try Ctrl+D, or pipe the input from a file (java myclass < input.txt).
it doesn't work because you have not programmed a fail-safe into the code. java sees that the scanner can still collect input while there is input to be collected and if possible, while that is true, it keeps doing so. having a scanner test to see if a certain word, like EXIT for example, is fine, but you could also have it loop a certain number of times, like ten or so. but the most efficient approach is to ask the user of your program how many strings they wish to enter, and while the number of strings they enter is less than the number they put in, the program shall execute. an added option could be if they type EXIT, when they see they need less spaces than they put in and don't want to fill the next cells up with nothing but whitespace. and you could have the program ask if they want to enter more input, in case they realize they need to enter more data into the computer.
the program would be quite simplistic to make, as well because there are a plethera of ways you could do it. feel free to ask me for these ways, i'm running out of room though. XD
If you don't want to use an EOF character for this, you can use StringTokenizer :
import java.util.*;
public class Test{
public static void main(){
Scanner sc = new Scanner (System.in);
System.out.print("Enter your sentence: ");
String s=sc.nextLine();
StringTokenizer st=new StringTokenizer(s," ");//" " is the delimiter here.
while (st.hasMoreTokens() ) {
String s1 = st.nextToken();
System.out.println(s1);
}
System.out.println("The loop has been ended");
}
}
I had the same problem and I solved it by reading the full line from the console with one scanner object, and then parsing the resulting string using a second scanner object.
Scanner console = new Scanner(System.in);
System.out.println("Enter input here:");
String inputLine = console.nextLine();
Scanner input = new Scanner(inputLine);
List<String> arg = new ArrayList<>();
while (input.hasNext()) {
arg.add(input.next().toLowerCase());
}
You can simply use one of the system dependent end-of-file indicators ( d for Unix/Linux/Ubuntu, z for windows) to make the while statement false. This should get you out of the loop nicely. :)
Modify the while loop as below. Declare s1 as String s1; one time outside the loop. To end the loop, simply use ctrl+z.
while (sc.hasNext())
{
s1 = sc.next();
System.out.println(s1);
System.out.print("Enter your sentence: ");
}

Java : How to use scanner.hasNextLine without Ctrl+Z in a console program

Say I have the below code
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
line = scanner.nextLine();
//do something
}
And my input in the console is goes like this.
Wayne Rooney
Luis Nani
Shinji Kagawa
I want to read this line by line.
But the problem is the method hasNextLine blocks waiting for the input after the third line as the input from the keyboard (System.in) never reaches EOF.
Now, how do I reach EOF just by pressing enter key? because I don't want to tell the user to press the Ctrl+z to run my program.
How is it generally done? Any thoughts?
I am looking for a solution from the Java side and not any commands on the console.
Thanks in advance
When you press enter twice, you end up reading an empty line. You can test for this:
while (scanner.hasNextLine()) {
line = scanner.nextLine();
if (line.equals(""))
break; // this will exit the loop
//do something
}
Now, the loop will end if you press enter twice without typing anything between.
How is it generally done?: It is usually done by showing a message to the user and requesting some special word to finish the input.
public static void main(String[] args) throws IOException
{
Scanner scanner = new Scanner(System.in);
String line;
System.out.println("Enter names (\"QUIT\" to finish)");
while (scanner.hasNextLine()) {
line = scanner.nextLine();
if (line.equals("QUIT")) {
break;
}
}
// ...
}
In the example above the special word used is "QUIT", of course you will change this to a more appropriated one.

How to get out of while loop in java with Scanner method "hasNext" as condition?

I ran into an issue. Below is my code, which asks user for input and prints out what the user inputs one word at a time.
The problem is that the program never ends, and from my limited understanding, it seem to get stuck inside the while loop. Could anyone help me a little?
import java.util.Scanner;
public class Test{
public static void main(String args[]){
System.out.print("Enter your sentence: ");
Scanner sc = new Scanner (System.in);
while (sc.hasNext() == true ) {
String s1 = sc.next();
System.out.println(s1);
}
System.out.println("The loop has been ended"); // This somehow never get printed.
}
}
You keep on getting new a new string and continue the loop if it's not empty. Simply insert a control in the loop for an exit string.
while(!s1.equals("exit") && sc.hasNext()) {
// operate
}
If you want to declare the string inside the loop and not to do the operations in the loop body if the string is "exit":
while(sc.hasNext()) {
String s1 = sc.next();
if(s1.equals("exit")) {
break;
}
//operate
}
The Scanner will continue to read until it finds an "end of file" condition.
As you're reading from stdin, that'll either be when you send an EOF character (usually ^d on Unix), or at the end of the file if you use < style redirection.
When you use scanner, as mentioned by Alnitak, you only get 'false' for hasNext() when you have a EOF character, basically... You cannot easily send and EOF character using the keyboard, therefore in situations like this, it's common to have a special character or word which you can send to stop execution, for example:
String s1 = sc.next();
if (s1.equals("exit")) {
break;
}
Break will get you out of the loop.
Your condition is right (though you should drop the == true). What is happening is that the scanner will keep going until it reaches the end of the input. Try Ctrl+D, or pipe the input from a file (java myclass < input.txt).
it doesn't work because you have not programmed a fail-safe into the code. java sees that the scanner can still collect input while there is input to be collected and if possible, while that is true, it keeps doing so. having a scanner test to see if a certain word, like EXIT for example, is fine, but you could also have it loop a certain number of times, like ten or so. but the most efficient approach is to ask the user of your program how many strings they wish to enter, and while the number of strings they enter is less than the number they put in, the program shall execute. an added option could be if they type EXIT, when they see they need less spaces than they put in and don't want to fill the next cells up with nothing but whitespace. and you could have the program ask if they want to enter more input, in case they realize they need to enter more data into the computer.
the program would be quite simplistic to make, as well because there are a plethera of ways you could do it. feel free to ask me for these ways, i'm running out of room though. XD
If you don't want to use an EOF character for this, you can use StringTokenizer :
import java.util.*;
public class Test{
public static void main(){
Scanner sc = new Scanner (System.in);
System.out.print("Enter your sentence: ");
String s=sc.nextLine();
StringTokenizer st=new StringTokenizer(s," ");//" " is the delimiter here.
while (st.hasMoreTokens() ) {
String s1 = st.nextToken();
System.out.println(s1);
}
System.out.println("The loop has been ended");
}
}
I had the same problem and I solved it by reading the full line from the console with one scanner object, and then parsing the resulting string using a second scanner object.
Scanner console = new Scanner(System.in);
System.out.println("Enter input here:");
String inputLine = console.nextLine();
Scanner input = new Scanner(inputLine);
List<String> arg = new ArrayList<>();
while (input.hasNext()) {
arg.add(input.next().toLowerCase());
}
You can simply use one of the system dependent end-of-file indicators ( d for Unix/Linux/Ubuntu, z for windows) to make the while statement false. This should get you out of the loop nicely. :)
Modify the while loop as below. Declare s1 as String s1; one time outside the loop. To end the loop, simply use ctrl+z.
while (sc.hasNext())
{
s1 = sc.next();
System.out.println(s1);
System.out.print("Enter your sentence: ");
}

Categories