Understanding the "read" method from System.in class [duplicate] - java

class E92StringDemo {
public static void main(String args[]) throws java.io.IOException {
String strObj1 = "First String";
for (int i = 0; i < strObj1.length(); i++) {
System.out.print(strObj1.charAt(i));
System.in.read(); //just to pause the execution till i press enter key
}
}
}
I want the output to come like:
F
i
r
s
t...
but the output is coming like:
F
ir
st
S
tr
in
g
I am not sure how come 2 characters are getting displayed in one line with every press of an enter key(\n)?
I am running windows 8 and using a command prompt to run the file using javac.

Problem
System.in.read() only holds execution of your application if there is no data to read in standard input stream (represented by System.in).
But in console when you press ENTER, two things happen:
console cursor is moved to next line
OS dependent line separator* is placed in standard input, which for Windows is \r\n:
carriage return \r - placed at index 13 in Unicode Table
line feed \n - placed at index 10 in Unicode Table
So as you see if you want to pause your loop in each next iteration, you will need to empty data from input stream before leaving current iteration. But System.in.read() reads only one character at a time, in your case \r leaving \n for next iteration (so no pause there).
So before pause will be again available you need to read twice in one iteration.
Solution
If you want to get rid of this problem in OS independent way use BufferedReader#readLine() or Scanner#nextLine like:
String strObj1 = "First String";
try(Scanner sc = new Scanner(System.in)){//will automatically close resource
for (int i = 0; i < strObj1.length(); i++) {
System.out.print(strObj1.charAt(i));
sc.nextLine();
}
}
These methods also solve problem of potential extra characters placed before pressing enter, since each of them will also be placed in standard input stream, which would require additional .read() calls.
* along with rest of potential characters which ware provided before pressing enter

ENTER on Windows generates 2 characters (CRLF) whereas read() only consumes 1 of them.
You must consume 2 characters for the desired behaviour. Just add another System.in.read() and you will see.
The following explains the generation and consumption of characters when you press ENTER. 13 represents CR and 10 represents LF.
F
13i10r
13s10t
13 10S
13t10r
13i10n
13g10

This will fix the problem you are having, but i cannot explain why you are getting this strange behavior with System.in.read().
class E92StringDemo {
public static Scanner reader = new Scanner(System.in);
public static void main(String[] args) {
String strObj1 = "First String";
for(int i = 0; i < strObj1.length(); i++) {
System.out.print(strObj1.charAt(i));
reader.nextLine(); //just to pause the execution till i press enter key
}
}
}

use
new Scanner(System.in).nextLine();
instead of
System.in.read();
Also you are getting this result using System.in.read because It returns an int besides all the possible values of a byte, it also needs to be able to return an extra value to indicate end-of-stream. So, it has to return a type which can express more values than a byte can.
However as per its Doc.
/**
* Reads the next byte of data from the input stream. The value byte is
* returned as an <code>int</code> in the range <code>0</code> to
* <code>255</code>. If no byte is available because the end of the stream
* has been reached, the value <code>-1</code> is returned. This method
* blocks until input data is available, the end of the stream is detected,
* or an exception is thrown.
*
* <p> A subclass must provide an implementation of this method.
*
* #return the next byte of data, or <code>-1</code> if the end of the
* stream is reached.
* #exception IOException if an I/O error occurs.
*/
public abstract int read() throws IOException;

Related

is it possible to scan multiple lines of input, each line a new element in an array, when you copy/paste?

Trying to populate an array with input through the scanner .nextLine() function. The problem specifications give a sample input as follows:
3 5 4
abc
bca
dac
dbc
cba
(ab)(bc)(ca)
abc
(abc)(abc)(abc)
(zyx)bc
Just as I copied and pasted that whole chunk into this box, I'd like to do the same with my code, but when I try, the code only reads in the last line. I want each line to be read in and stored in it's own index in the array, NOT a multi-line string in one index or only the last line being read in and stored (which is what is happening now).
This is my method for initializing the array, which I've tested and it works when I feed in the input line by line, but that's just really annoying to be honest.
public static void initialize_array(String [] arr)
{
Scanner kbreader = new Scanner(System.in);
for (int i = 0 ; i < arr.length ; i++)
{
arr[i] = kbreader.nextLine();
System.out.println("this is just loading in: " + arr[i]);
}
}
When I run the program, (it also takes in 3 integers at the top and I print them just to test them, but that's not important) it only registers the last line.
A screenshot:
enter image description here
I think I've done something like this in C, but that might be because I used scanf() and C is relatively low level so it literally had to walk through the entire chunk.
It might not be possible, but I figured I'd ask to see.
Also, just so you know this is for practice, not an actual graded assignment or anything important, so don't hold anything back. :)
If you know the exact length of the array, then this would work:
Scanner scn = new Scanner(System.in);
scn.useDeliminator("\n");
for (int i = 0 ; i < arr.length ; i++)
{
arr[i] = scn.next();
System.out.println("this is just loading in: " + arr[i]);
}
The key here is the useDeliminator method call. The next methods reads from the stream until it reaches the deliminator pattern. In this case, it is \n, a new line. Please use the new line character of your OS.
This may be off point, but have you tried just using array.add(scanner.next()) and looping until scanner.hasNext() returns false?

confused with buffered reader in java

when i run the code only with //1 - start, the output is ascii value of input character
when i run the code only with //2 - start, the output is the entered string terminated by newline character
when i run the code with both (as shown in below code), only //1 - start executes, readLine() is being considered in a strange way.
when i run the code with both (with //2 - start placed above //1 - start), both the codes executes fine,
Please explain why this strange behavior happens in case 3 but not in case 4.
public class InputBufferedReader {
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
//1-start
//read one character
System.out.println("enter input: ");
int b= br.read();
System.out.println(b);
//end
//2-start
//read a string
System.out.println("enter input string: ");
String a = br.readLine();
System.out.println(a);
//end
} catch (IOException e) {
e.printStackTrace();
}
}
}
Your BufferedReader uses the InputStreamReader with System.in. The BufferedReader uses the read() method from InputStreamReader to read the data from the standard input stream System.in. Now lets look into the API for this read() method.
[...] This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
Blocking means in this context waits for user to input data throu the console confirming with the Enter Key.
With that in mind lets examine your cases.
1. int b= br.read(); Nothing is already typed, so this method blocks until user typed something and then prints the ascci value of first character.
2. String a = br.readLine(); Nothing is already typed, so this method blocks until user typed something and then prints the whole line.
3.
int b= br.read();
Lets image user typed a confirming with Enter Key that means the input is a\n. Now read() reads the first character which is a.
String a = br.readLine();
This read() call will not block and ask for user input because there is unconsumed input left \n. So readLine() will read \n.
4.
String a = br.readLine();
User is asked for input which is confirmed with Enter Key. And the whole line will be read.
int b= br.read();
There are no unconsumed data left, because readLine() already has read the whole line including \n character. So this read() call blocks and user is asked for input.
int read() method attempts to Read Next Character from the Console(or File) and Return its Unicode Value,
As this Method Returns Unicode Value Compulsory at the Time of Printing we- should perform type- Casting.
If there is No Next Character the we will get -1.
String readLine() Method attempts to Read Next Line from Console(or File) and Returns it, if it is available.
If the Next line is Not available, then return null.

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.

How to stop reading multiple lines from stdin using Scanner?

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.

A simple Java code that doesn't work well

The following simple code in Java behaves somewhat in a strange way that I can not understand.
final public class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
System.out.print("\nHow many names? ");
int n = sc.nextInt();
String[] a = new String[n];
a[0] = sc.nextLine(); //This line serves no purpose at all. It's useless and should be removed.
for (int i=0; i<n; i++)
{
System.out.print("\nEnter the name:->");
a[i] = sc.nextLine(); //request for input only inside the loop.
}
for (int i=0; i<a.length; i++)
{
System.out.println(a[i]);
}
}
}
The above is working well with no problem at all and displays the number of names inputted into the array a[] on the console but when I remove the line a[0] = sc.nextLine(); //This line serves no purpose at all. It's useless and should be removed., it displays for number of users first. let's say 3. there is no problem but when the loop starts iterating, it will ask for the name and first time the message Enter the name:-> is displayed twice
and the output would be something like shown below.
How many names? 3
Enter the name:-> Don't allow to enter the name here.
Enter the name:->Tiger
Enter the name:->Pitter
Tiger
Pitter
Although I entered 3 for "How many names?", it allows only two names to enter. Why?
Note again that the code shown above is working well. The problem occurs only when the line specified with bold latters in the above paragraph is commented out.
When you use Scanner.nextInt(), it does not consume the new line (or other delimiter) itself so the next token returned will typically be an empty string. Thus, you need to follow it with a Scanner.nextLine(). You can discard the result instead of assigning it to a[0]:
int n = sc.nextInt();
sc.nextLine();
It's for this reason that I suggest always using nextLine (or BufferedReader.readLine()) and doing the parsing after using Integer.parseInt().
You are reading three lines. The problem you have is that nextInt() reads an int value, it doesn't read and consume the end of the line. (A common mistake)
You need the nextLine() after it to say that you want to ignore the rest of the line.
The nextInt call reads from input until the end of the int, but does not read the newline character after the int. So, the first iteration displays "enter the name", then calls nextLine() which reads the end of the line where you typed the number of players (an empty string). Then the second iteration starts and displays "enter the name", and nextLine() blocks until you type a newline character.

Categories