How to stop reading multiple lines from stdin using Scanner? - java

I'm working on an JAVA assignment should process multiple lines of input. The instructions read "Input is read from stdin."
An example of sample input is given:
one 1
two 2
three 3
I don't understand what the above sample input "read from stdin" means.
Here's a test program I wrote that isolates my confusion:
import java.io.*;
import java.util.Scanner;
class Test
{
public static void main(String[] args)
{
Scanner stdin = new Scanner(System.in);
while(stdin.hasNextLine())
{
String line = stdin.nextLine();
String[] tokens = line.split(" ");
System.out.println(Integer.parseInt(tokens[1]));
}
}
When I run this program in the console, it waits for my input and each time I input a line it echos it back as I would expect. So I thought perhaps the sample input above would be achieved by entering each of the 3 lines in this fashion. However, there seems to be no way to end the process. After I enter the 3 lines, how do I terminate the input? I tried just pressing enter twice, but that seems to read as a line consisting of only the newline character, which causes an error because the line doesn't fit the 2 token format it expects.
Here's what the console interaction looks like:
javac Test.java
java Test
one 1
1
two 2
2
three 3
3
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at Test.main(Test.java:13)
I'd appreciate any help in pointing out the gap in my understanding.

You could try asking for empty inputs
import java.util.Scanner;
public class Test
{
public static void main(String[] args)
{
String line;
Scanner stdin = new Scanner(System.in);
while(stdin.hasNextLine() && !( line = stdin.nextLine() ).equals( "" ))
{
String[] tokens = line.split(" ");
System.out.println(Integer.parseInt(tokens[1]));
}
stdin.close();
}
}
Your code is almost completed. All that you have to do is to exit the while loop. In this code sample I added a condition to it that first sets the read input value to line and secondly checks the returned String if it is empty; if so the second condition of the while loop returns false and let it stop.
The array index out of bounds exception you will only get when you're not entering a minimum of two values, delimitted by whitespace. If you wouldn't try to get the second value >token[1]< by a static index you could avoid this error.
When you're using readers, keep in mind to close after using them.
Last but not least - have you tried the usual Ctrl+C hotkey to terminate processes in consoles?
Good luck!

You could also put your values in a file e.g. input.txt and do:
java Test < input.txt

From the shell, hit Ctrl-D and it will close stdin. Alternatively, pipe input in
cat your-input-file | java Test

To stop the input, you could either prompt the user to enter quit to exit, and then test for the presence of that String in the input, exiting the loop when found, or you could use a counter in the loop, exiting the loop when the maximum iterations have been reached. The break statement will get you out of the loop.

Related

How can I check if the user has input one or two values?

I am writing a program where the user can input up to two values, so if the user inputs one value, it calls the first constructor and if the user inputs 2 values the second constructor is called, but the issue is when the user inputs one value and press enter, the program will be waiting for the second value.
Basically, I want the program to execute the function based on the number of inputs. Also, I can't ask the user how many inputs he wants to add before either.
Basically, I'm trying to see if writing java ValuM 5 or java ValuM 5 6 in the command line and get the right function executed.
Someone said it to use the timer Class, to put it in a timeout, but I'm not sure how it works, or if there is an easier way to do this.
import java.util.Scanner;
import java.util.Timer;
public class ValueM {
public static void main(String[] args) {
Scanner myObj = new Scanner(System.in);
int first_Input=myObj.nextInt();
int Second_Input=myObj.nextInt();
ValueM array_gen=new ValueM(first_Input);
array_gen=new ValueM(Second_Input,first_Input);
}
}
What you could do is to require the user to enter both numbers on the same line. That way you could use myObj.nextLine() and check if it contains one or two numbers. (I would rename myObj to scanner or something similar.)
To check if the line contains one or two numbers, you could create a second Scanner with the line as the source: Scanner lineScanner = new Scanner(line);, then use lineScanner.nextInt() to read the first number and lineScanner.hasNextInt() to check if there is a second one.
Your input values look like command line arguments so you don't need to use Scanner. Try this:
public static void main(String[] args) {
ValueM array_gen;
if (args.length == 1) {
array_gen=new ValueM(Integer.parseInt(args[0]));
} else if (args.length == 2) {
array_gen=new ValueM(Integer.parseInt(args[1]),Integer.parseInt(args[0]));
} else {
// message user about bad input
}
}

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

java: Scanner asks for an extra value when using useDelimiter

So I wanna create this program that stores 4 values. the first one being string and the remaining 3 being integers. However, when i enter 4 values and press enter, i get an error java.util.InputMismatchException but when I enter 5 values, i get the result for my for values. for example lets say i input the following values:
Japan,1,2,3
I will get the java.util.InputMismatchException error. And if I enter the following values:-
Japan,1,2,3,4
I get the output as I want:-
Japan,1,2,3
Why is this happening? Here is my code
public class satisfaction {
public static void main(String args[])
{
Scanner src= new Scanner(System.in);
src.useDelimiter("\\,|\\n");
String name=src.next();
int a=src.nextInt();
int b=src.nextInt();
int c=src.nextInt();
System.out.println(name+","+a+","+b+","+c);
}
}
I've tested this a bit myself, and I think the \n in the pattern is not matching the line ending used by your console.
For me, I had to use \r\n instead, but you could also use System.lineSeparator() e.g. like this:
src.useDelimiter(",|" + System.lineSeparator());
The way it's written, it needs another comma at the end of the input. I would recommend checking the string to make sure it ends in a comma, and if not, append one.
I believe that if you enter Japan,1,2,3, it will give you the output you want.

findWithinHorizon(".",0).charAt(0) Clarification

I'm having trouble understanding the source below:
myChar1 = myScanner.findWithinHorizon(".",0).charAt(0);
System.out.println(myChar1);
myChar2 = myScanner.findWithinHorizon(".",0).charAt(0);
System.out.print(myChar2);
I understand what it does, but I'm just having a bit of a trouble understanding how it works.
The actual prompting of the user for input is done at the first line right? but the real meaning of the first line is: "put the first char of input in myChar1". Then what happens? It seems the input still stays inside myScanner because when I use it in myChar2 I get the second char, but why? why not the first char? Does findWithinHorizon(".",0).charAt(0) deletes the char that is assigned to the variable?
And last question: if in the first line the program prompts the user for input why doesn't it do it again in the second line?
Also, a quick recap of the (".",0) would be helpful as well.
Perhaps the piece you are missing is that findWithinHorizon actually takes a regular expression as the String argument. In a regular expression, . matches any character (except a new line).
A call to findWithinHorizon(".", 0) simply finds the next character in the input and advances the Scanner past whatever was found.
So for example,
Scanner in = new Scanner("abc123");
for(;;) {
String found = in.findWithinHorizon(".", 0);
if(found == null) break;
System.out.println(found);
}
the output is:
a
b
c
1
2
3
The reason it does not prompt for input at the second line is that is the way Scanner and System.in work together. They will only block and prompt for input if there is no more existing input to consume. As a short example, try this out:
Scanner in = new Scanner(System.in);
while(true) {
System.out.println(in.findWithinHorizon(".", 0));
}
That will loop infinitely, repeating back whatever you input, character by character. It will only prompt for more when it's done with the prior input. On the first iteration, Scanner will call read on System.in which will block and wait for input. When the input runs out, read will block again.

Reading lines of input from user using SCANNER

I have a program that needs to read lines of input. It needs to be many lines at once. For example:
As I enter my time machine or
maybe not,
I wonder whether free will exists?
I wonder whether free will exists
maybe not
as I enter my time machine or.
That all gets entered at one time by the user. I was trying to use .hasNextLine() method from Scanner class, but it is not returning false.... it waits for input again. Ive been looking around for a solution and it appears that .hasNextLine() waits for input, but i do not know what alternative to use. Any suggestions? The actual code looks like:
while(input.hasNextLine());
{
line += input.nextLine();
}
Thanks for your help
Perhaps you should use some sort of "stop" sequence meaning when the user enters a particular character sequence, it will break out the loop. It might look something like:
public static void main(String args[]){
final String stopSequence = "/stop";
final Scanner reader = new Scanner(System.in);
String input = reader.nextLine();
while(!input.equalsIgnoreCase(stopSequence)){
//process input
input = reader.nextLine();
}
}

Categories