System.in.read () behavior I cannot explain
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 result to be like this:
F
i
r
s
t...
but the output goes like this:
F
ir
st
S
tr
in
g
I'm not sure why two characters appear on the same line each time the enter
(\ n) key is pressed ?
I am running windows 8 and using command line to run the file with javac
.
ENTER on Windows generates 2 characters (CRLF) whereas read () only consumes 1 of them. You must consume 2 chars for the desired behavior. Just add more System.in.read()
and you will see.
The generation and consumption of characters by pressing ENTER is explained below. 13 is CR and 10 is LF.
F
13i10r
13s10t
13 10S
13t10r
13i10n
13g10
source to share
Problem
System.in.read()
only execution of your application is executed if there is no data to read on the standard input stream (presented System.in
).
But in the console, when you press ENTER, two things happen:
- the console cursor moves to the next line
-
The OS- specific * line separator is placed on standard input, which for Windows is
\r\n
:- carriage return
\r
- placed at index 13 in the Unicode table - line feed
\n
- placed at index 10 in the Unicode table
- carriage return
So, as you can see, if you want to pause the loop in every next iteration, you will need to clear data from the input stream before exiting the current iteration. But it System.in.read()
only reads one character at a time, in your case \r
, leaving \n
for the next iteration (so there is no pause).
So, before the pause is available again, you need to read twice in one iteration.
Decision
If you want to get rid of this problem offline OS, 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 the problem of potential extra characters placed before pressing enter, since each of them will also be placed on standard input, which will require additional calls .read()
.
* along with the rest of the potential characters that were provided before hitting enter
source to share
This will fix the problem you are facing, 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
}
}
}
source to share
use
new Scanner(System.in).nextLine();
instead
System.in.read();
Also you get this result with System.in.read
, because it returns int
in addition to all possible byte values, it must also be able to return an additional value to indicate the end of the stream. Thus, it must return a type that can express more values than bytes.
However, according to 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;
source to share