Continue reading console input after Ctrl+Z in Java - java

For a university assignment, from the console I need to be able to read in multiple lines until the user enters Ctrl+Z. That I have no issue with, my problem lies with me being unable to read anything in from System.in after that because it always throws a NoSuchElementException.
The following is the code that I am using for reading in the multiple lines, it was provided by the instructor and so I don't want to change it.
System.out.println("To terminate input, type the correct end-of-file indicator ");
System.out.println("when you are prompted to enter input.");
System.out.println("On UNIX/Linux/Mac OS X type <ctrl> d");
System.out.println("On Windows type <ctrl> z");
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
//Processes input
addFileIntoDirectory(input.nextLine());
}
I understand that this is caused by the Ctrl+Z which equates to an EOF marker, but I don't know how to move past it. No matter how many reads after it I do, regardless of if I have typed more to the console, I just instantly get back another NoSuchElementException.
I have tried having a separate scanner for the menu, closing the scanner above and opening a new one for the menu but neither works.
Is there a way to flush/purge System.in or to reset it?
Please let me know if you would like more details. I have kept the rest of the program vague as it is homework.
EDIT 1: Assignment says "The system provides a textual selection menu as follows, and
runs in loop." Which means the program is not to terminate on Ctrl+Z.
add files from user inputs
display the whole directory
display the size of directory
exit
Please give a selection [0-4]:

The short answer is:
if (!input.hasNext())
input = new Scanner(System.in);
The long answer is:
Below is code, with comments made for removing later, to demonstrate the problem as I understand it and solution.
Note this demo is intended to only work with integer and ^Z inputs.
Copy out the code and save into file HN.java to compile.
Run the program and it will prompt One. Enter integers to your heart's content and exit the loop by entering ^Z.
Two will be displayed followed by the NoSuchElementFound exception in the question. This is because the ^Z remains in the Scanner object input and thereby fails on the nextInt() method.
The first inclination might be to use hasNext() to account for this. So go ahead and uncomment /*Comment1 and recompile and run again.
Now you avoid the exception, but the program blazes through to the end, skipping over the nextInt() originally intended.
So now, uncomment /*Comment2, recompile, and run again. Now the program will wait at the Two prompt as intended. If you enter an integer here, you will proceed to the Three prompt for another entry.
However, if you enter ^Z at Two, again, the program skips the next input. To correct this, uncomment /*Comment3, recompile, and run, and you will see the program works for all combos of integers and ^Z at the various inputs.
Now, you might be wondering why I didn't just reuse the !input.hasNext() solution in /*Comment3. Here's a demo why:
Put back the /*Comment3 and uncomment the /*Comment4, compile and run again. The program works fine and dandy with a ^Z input at the Two prompt, but if you enter an integer there, you'll see the system waiting for input, but there is no prompt Three!
This is because the integer you entered was used in the preceding nextInt() so when the program gets to the hasNext(), it stops and waits for input.
The lesson here is you use the !input.hasNext() when you KNOW you have a ^Z in queue such as when it was used to escape the while loop in this program and the original poster's question. Otherwise the else structure is better suited.
hasNext() is confusing to work with. You have to keep in mind that if nothing is in queue the program will stop and wait for input at that point. This may mess up your prompting if you're not careful.
import java.util.Scanner;
public class HN
{
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
int temp = 0;
System.out.println("One");
while (input.hasNext())
{
temp = input.nextInt();
}
System.out.println("Two");
/*Comment2
if(!input.hasNext()) input = new Scanner(System.in);
Comment2*/
/*Comment1
if (input.hasNext())
Comment1*/
{
temp = input.nextInt();
System.out.printf("%d\n", temp);
}
/*Comment3
else input = new Scanner(System.in);
Comment3*/
/*Comment4
if(!input.hasNext()) input = new Scanner(System.in);
Comment4*/
System.out.println("Three");
if (input.hasNext())
{
temp = input.nextInt();
System.out.printf("%d\n", temp);
}
System.out.println("Four");
}
}

Related

scanner doesn't close using scan.NextInt() and .hasNext() loop

I'm trying to read the Input below but the Scanner doesn't close in Java. From the output, I can see all the inputs are taken inside the string, but the console still shows the program is still running. The red square button is still active. Can you please help?
4
0 3
2 5
4 2
4 0
Scanner scan = new Scanner(System.in);
String input = "";
scan.useDelimiter("\\s*");
while (scan.hasNext()) {
System.out.print(scan.nextInt());
}
The scanner doesn't know when you are going to stop entering data at the console (unlike reading from a file which signals an EOF). So it blocks, waiting for more input. So you have several options.
You can either type Ctrl-D (or what ever your OS requires to signal an EOF).
You can use special input to stop checking (Like a "Done" string) (which means you will need to parse ints if you want integer input too.)
Or you can initially prompt for an integer to indicate how much data to type in via a loop.
You can also do the following:
while (true) {
if (!scan.hasNextInt()) {
// requires a non-empty and non-numeric value.
break;
}
System.out.println(scan.nextInt());
}
But do not close the Scanner after reading from the console. Otherwise you will not be able to reopen it and take input within the same program.
I guess you are new to Java and software development. First, you should check the JavaDoc of the hasNext() method:
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Scanner.html#hasNext()
Citation: "This method may block while waiting for input to scan."
So you have a continuous loop. If you want to exit your loop, you have to do that explicitly.

Check input continuously on one line?

I am trying to make a simple code which continously checks the user input on if the number is positive or negative and that it would all be on 2 lines.
First line being the user input and the second line being the output.
I am a beginner in coding and am not such a professional, but I have right now put the Scanner object in a while loop and it checks if the user input is positive. If it's negative then it would stop the program.
import java.util.Scanner;
public class basic {
public static void main(String[] args){
int numb;
Scanner scanner = new Scanner(System.in);
System.out.println("Fill in a random number which ain't negative!");
while((numb = scanner.nextInt()) > 0) {
System.out.println("Again!");
}
{
System.out.println("This is a negative!");
System.exit(1);
}
}
}
What I want to do is that I get this as an output and only on 2 lines:
1 2 3 4 5
Again!
And if I input a negative number on the line that it changes the 'Again!' to 'This is a negative!'
1 2 3 4 5 6 -8
This is a negative!
But with the code I have now I can only get this as an output and would get much more than just 2 lines:
1
Again!
2
Again!
-3
This is a negative!
This is console output so cannot be overwritten.
But if you are really looking to the getting required o/p printed on the console, you can use list and keep pushing digits to it and print all the items of the list.
You could use \r to rewrite the last line. Consider that:
System.out.println("\r"+yourOutput+" > ")
It replaces the last line in the console with this one, that's how loading bars in linux are done by the way :D. Use this method to display your previous inputs/numbers. User input will be in the second line. When user has pressed enter and your program has gotten the user input as string, process it and do the same thing again, this time with yourOutput updated with new info:
System.out.println("\r"+yourOutput+" > ")
Let me welcome you to your first post on StackOverflow!
It is unusual to have java applications clearing the console output. That being said, it is possible, but not without calling OS commands. As mentioned in comments, this is a little beyond beginner material if you do this.
If you want to try it though, as seen here, you can clear the console by executing a native OS command. If you use the below code (copied from the link with a minor edit)
public static void clrscr(){
//Clears Screen in java
try {
if (System.getProperty("os.name").contains("Windows"))
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
else
Runtime.getRuntime().exec("clear");
} catch (Exception e) {}
}
you can call this with clrscr() in your code and you should be able to clear the screen.
Now looking at your code, you won't just be able to slip this in as you will clear the output, thus clearing the past numbers. If you want it the way that you described where you have all the user's output displayed in succession, you'll need to re-print all their entries each time you clear the screen. Thus each time you get a user's input:
You'll want to take that input and add it to a list of numbers
Clear the screen
Output that entire list
Output your evaluation
Let me know if you have questions. :-)

Don't understand how Java Scanner object is working in this example (hasNextInt, next...?)

In my program I need to take an input from a user, but it must be an integer. If the user doesn't input an integer, I need the program to reprompt them to enter an integer, and keep doing so until they enter one. I found an example while loop code snippet online which works perfectly, but I am having problems understanding why and how it works, and I'd really like to understand better:
Scanner reader = new Scanner(System.in);
int guess=0;
System.out.println("Guess the number");
while (!reader.hasNextInt()) { //I get that this is a "not have" boolean
System.out.println("That's not a number. Please enter a valid number");
reader.next();
}
guess= reader.nextInt();
System.out.println(guess);
My questions are:
Does the !hasNext condition in the while loop actually trigger the scanner object to ask the user for input and then check that input, or does it only check anything that has already been inputted?
Why is it necessary to have the reader.next(); line after the while loop's main statement and what is this doing exactly? I know it's necessary as the program doesn't work when I take it out. But is it prompting for input? If yes what happens to this input?
When guess= reader.nextInt(); runs, why doesn't it re-prompt the user for input at this point?
Sorry that these are probably really basic questions, I'm new to coding and Java and just can't get my head around what's happening internally in this particular example, though have no problem doing other basic stuff with the Scanner.
It's not particularly intuitive, for sure, so don't feel bad for not getting it immediately.
It seems to me that the problem you're having with your understanding is that that methods such as nextInt may or may not prompt for user input, depending if anything is already in the Scanner.
Here's the sequence of events:
All your code executes until you hit !reader.hasNextInt(). There's no input so it "blocks" (waits) until there is some input from the user.
If the user enters 'A', that's not an integer so we enter the body of the while loop. We then print the error message.
Now, hasNextInt doesn't "consume" (process) the user input when it's checking whether or not it's an integer, so we still have that invalid user input of 'A' sitting in our scanner. We call reader.next() to effectively discard that value.
Now we're back to !reader.hasNextInt(). The scanner is empty once again, so we prompt for user input. If they enter another non-integer, that process will simply keep repeating.
Say this time we do have a valid user input - they've entered the number 2. This passes the check so our while loop ends and we continue along.
We've now got some input in our scanner, but we've not consumed it. We're sure it's an integer because of the while loop condition. We can now consume the input with reader.nextInt() and assign it to our variable.
hasNextInt() only checks whether the next input is an integer. It won't consume any input at all. The ! is just negate theu outcome of this function.
As hasNextInt() won't consume, then we need to use next() to consumeo the user input to let hasNextInt() to check with user's next input value. As you won't need it at all, then no need to assign it to any variables.
Scanner won't display the prompt at all. The prompt is printed by System.out.println().
For the line nextInt(), it is used to consume the next user input. Since hasNextInt() must be true when it execute this line, there must be one integer input waiting for consumption, so this method can return immediately with that user input.
Try it :)
public static void main(String[] args) {
int option;
if(args!=null&&args.length>0){
option = Integer.parseInt(args[0]);
}
else{
System.out.println("Enter:\n 1 to run x \n 2 to run y \n");
Scanner keyboard = new Scanner(System.in);
option = keyboard.nextInt();
}
switch (option) {
case 1:
xx
break;
case 2:
yy
break;
default:
break;
}
}

How does this snippet work with the buffer? Java

So basically this code is supposed to keep asking "Please insert a valid number" until an integer is introduced through the keyboard. It works just fine, I'm just curious as to how it actually does what it does.
Scanner input = new Scanner(System.in);
System.out.println("Please insert the number of lives.");
while (!input.hasNextInt()) {
input.next();
System.out.println("Please insert a valid number.");
}
numberOfLives = input.nextInt();
In my head it would make more sense to put the numberOfLives = input.nextInt(); line inside of the while loop. This is basically what I'm understanding from this snippet once it reaches the while loop:
Check condition in while, if input scanner variable doesn't have an int value, do the following
Discard what is in the input scanner variable
Print out the valid number message
Obviously this isn't how it goes, else this snippet wouldn't work. I'm thinking maybe each time it checks the condition, the actual !input.hasNextInt() opens up the buffer again for input and THEN checks what's inside, but I have no clue.
Sorry if I'm not using the terms correctly, pretty now to all of this stuff.
Thanks!
Like an iterator, scanner will always point to the element before the stream starts. i.e. if the list starts with position 0, scanner will point to -1st position. next() will advance the scanner and return the element present at location.
In this code, we are checking if the next element is integer. If it is not, why to advance the scanner?

Why doesn't Scanner seem to look for a new int every time nextInt is called

Why does it continue in the while loop repeating "Please enter a valid number" and it keeps repeating without stopping to let the user input something.
while (true) { //This will continually run until something is returned, AkA the number 1 or 2
Scanner s = new Scanner(System.in);
try {
input = s.nextInt();
} catch (Exception e) {
System.out.println("Please enter a valid number!");
}
s.close();
}
When I use the debugger nothing seems to be the cause of this problem and no errors are thrown. What is causing this problem and how can it be fixed?
Closing a scanner also closes the underlying stream if it implements the Closable interface.
That's System.in in this case and, once closed, you won't be able to create a scanner using it again.
See http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#close() for the gritty detail.
But, even if you fix that problem, an exception from nextInt will not advance the stream pointer so, the next time you call it, it will find exactly the same data in the input stream again.
You need to clear out the erroneous data before trying again. Since you're accepting user input, one solution is to call nextLine and throw that away;
string junk = s.nextLine();
Remove
s.close();
And Define your Scanner object outside the while loop as it not an Issue. Btw, I've tried your code, it worked fine until I entered a input which is not an int. When I entered a string, the exception sysout statement keeps printing infinitely
So you've to add
string junk = s.nextLine();
in your Exception block like paxdiablo said so that it wont repeat continuously.

Categories

Resources