Java scanner frustrations - java

I have the following method:
private String doEntryScan(InputStream stream)
{
try (Scanner scanner = new Scanner(stream)) // Reading from System.in
{
String readString = scanner.nextLine();
if (readString.isEmpty())
{
readString = "\n";
}
scanner.nextLine(); //consume carriage returns if they remain
scanner.close();
return readString;
}
}
The idea is that the user can hit enter to accept defaults. Or they can enter something. If I include the line
scanner.nextLine(); //consume carriage returns if they remain
the method hangs at that point, presumably waiting for more input. If I don't have that line, I get a NoSuchElementException the next time I call this method. I'm assuming this is because there's a carriage return in the stream.
So how does one get around this? scanner.hasNext() doesn't help because it ALSO "sometimes" blocks.
By the way, in practice InputStream is System.in.

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());
}
}
}

Scanner.hasNextLine - always true

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)

Try Catch Exception stuck repeating in any while loop (Java) [duplicate]

This is the program
public class bInputMismathcExceptionDemo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean continueInput = true;
do {
try {
System.out.println("Enter an integer:");
int num = input.nextInt();
System.out.println("the number is " + num);
continueInput = false;
}
catch (InputMismatchException ex) {
System.out.println("Try again. (Incorrect input: an integer is required)");
}
input.nextLine();
}
while (continueInput);
}
}
I know nextInt() only read the integer not the "\n", but why should we need the input.nextLine() to read the "\n"? is it necessary?? because I think even without input.nextLine(), after it goes back to try {}, the input.nextInt() can still read the next integer I type, but in fact it is a infinite loop.
I still don't know the logic behind it, hope someone can help me.
The reason it is necessary here is because of what happens when the input fails.
For example, try removing the input.nextLine() part, run the program again, and when it asks for input, enter abc and press Return
The result will be an infinite loop. Why?
Because nextInt() will try to read the incoming input. It will see that this input is not an integer, and will throw the exception. However, the input is not cleared. It will still be abc in the buffer. So going back to the loop will cause it to try parsing the same abc over and over.
Using nextLine() will clear the buffer, so that the next input you read after an error is going to be the fresh input that's after the bad line you have entered.
but why should we need the input.nextLine() to read the "\n"? is it necessary??
Yes (actually it's very common to do that), otherwise how will you consume the remaining \n? If you don't want to use nextLine to consume the left \n, use a different scanner object (I don't recommend this):
Scanner input1 = new Scanner(System.in);
Scanner input2 = new Scanner(System.in);
input1.nextInt();
input2.nextLine();
or use nextLine to read the integer value and convert it to int later so you won't have to consume the new line character later.
Also you can use:
input.nextInt();
input.skip("\\W*").nextLine();
or
input.skip("\n").nextLine();
if you need whitespaces before line

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.

Counting carriage return, Java

I am trying to count carriage return occurrences within string input. I tried both Scanner and BufferedReader. With Scanner, nextLine() does not pick up Carriage Returns. next() with Scanner looks for tokens, such as a space in input, and token splits up the input. I want the entire input to be read as single input. This probably means I cannot use Scanner.
With BufferedReader, readLine() reads up to a Carriage Return, but does not return a Carriage Return in input. If I use "reader.read();" then it tells me that the variable user_input HAS to be int. user_input is supposed to be a string input that MAY have an integer, but it also may not. The only thing is that program would continue until input contains "/done". I would appreciate it if somebody would simply point me in the right direction!
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String user_input = "";
System.out.println("Enter a string: ");
while (!user_input.contains("/done")) {
user_input = reader.readLine(); //cannot be readLine because it only reads up to a carriage return; it does NOT return carriage return
//*Sadly, if I use "reader.read();" then it tells me that user_input HAS to be int. user_input is a string input
String input = user_input;
char[] c = input.toCharArray();
int[] f = new int[114];
System.out.println("Rest of program, I convert input to ascii decimal and report the occurences of each char that was used");
}
catch (IOException e) {
e.printStackTrace();
}
}
Is this what you're looking for?
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("\\z"); //"\\z" means end of input
String input = scanner.next();
EDIT: If you want the "\n" to show as "CR", just do this:
input.replaceAll("\\n", "CR");
There's a library called StringUtils that can do this very easily. It has a method named countMatches. Here's how you can use it. But first, you should combine your input into one string:
package com.sandbox;
import org.apache.commons.lang.StringUtils;
public class Sandbox2 {
public static void main(String[] args) {
String allInput = "this\nis\na\n\nfew\nlines\nasdf";
System.out.println(StringUtils.countMatches(allInput, "\n"));
}
}
This outputs "6".
Read characters one by one until EOF is encountered using read() method.
JAVA DOCS
read() in java reads any character(even \n, \r or \r\n). Thus read character one by one and check whether the character read in "Carriage return" or not.
If yes, then increase the counter.

Categories