confused with buffered reader in java - 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.

Related

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

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;

how to take char input before int input in java?

public class Pack1 {
public static void main(String ar[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter the character");
char c=(char)br.read();
System.out.println(c);
System.out.println("enter the integer");
long l=Integer.parseInt(br.readLine());
System.out.println("long l="+l);
System.out.println(c);
}
}
Let's say the user types X and presses Enter on the first question, then types 123 and presses Enter on the second question, that would mean that the input stream contains the following characters:
X <CR> 1 2 3 <CR>
When you call read(), you only read the X. When you then call readLine(), you read the <CR> and get a blank string back.
The 1 2 3 <CR> is still sitting unread in the input stream.
Solution: Call readLine() after reading the X to skip past the rest of the line, or use readLine() to read the X as a String, instead of as a char.
FYI: This is the exact same problem people keep having when using Scanner and mixing calls to nextLine() with calls to other nextXxx() methods, like nextInt().
Change this:
long l=Integer.parseInt(br.readLine());
to :
long l=Long.parseLong(br.readLine(), 10);
This is because you are trying to convert the String to Long and not an Integer type.

Substring Removal from a string using stream buffer class in java-Output wrong-Verify

Substring Removal from a string using stream buffer class in java.
Output coming wrong:
Please verify this Program
See my output and explain what the program is about?
What must be the desired output and what changes must be made in the program to get the corrct output?
import java.io.*;
public class Strbuff
{
public static void main(String arg[])throws IOException
{
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
String str;
try
{
System.out.println("Enter your name");
str=in.readLine();
str+="\nThis is example for string Buffer class and its function";
StringBuffer strbuf=new StringBuffer();
strbuf.append(str);
System.out.println(strbuf);
strbuf.delete(0,str.length());
strbuf.append("hello");
strbuf.insert(5,"-java");
System.out.println(strbuf);
strbuf.reverse();
System.out.println("Reversed string");
System.out.println(strbuf);
strbuf.reverse();
System.out.println(strbuf);
strbuf.setCharAt(5,' ');
System.out.println(strbuf);
System.out.println("Character at 6th position");
System.out.println(strbuf.substring(3,7));
strbuf.deleteCharAt(3);
System.out.println(strbuf);
System.out.println("Capacity of the string Buffer object");
System.out.println(strbuf.capacity());
strbuf.delete(6,strbuf.length());
System.out.println("The string with first 6 letters");
System.out.println(strbuf);
}
catch(StringIndexOutOfBoundsException e)
{
System.out.println(e.getMessage());
}
}
}
This is basic beginner material and you must have already covered and touched onto the methods that will allow you to establish what this code does. At the very least you will have been provided with (or the location of) the reading material you require to carry out the requested task.
All you need to do is actually do what is asked of you. Instead, you thought you would come to StatckOverflow and have someone else do your homework for you which is not what the forum is for. We are here to help you with the stumbling blocks you trip over while walking on your path to being a Java Programmer but, you must at the very least show an attempt to pick yourself up when you stumble. Copy/Pasting your homework code here is not considered trying.
Step through each line of code and place a comment consisting of a brief description of what that line does over each line. If you don't know what the code line does then read about the method you are having trouble with. Try different things with that method and before you know it, you will have a full understanding of it.
I will help get you started:
// Open a BufferReader InputStream and establish it as variable 'in'...
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
// Declare a String variable named 'str'. This string is not originally
//initialized so I'm going to do that now with a Null String...
String str = "";
// Establish a try/catch block to trap a StringIndexOutOfBoundsException
// should it ever occur. This exception is thrown by String methods to
// indicate that an index is either negative or greater than the size of
// the string. For some methods such as the charAt method, this exception
// also is thrown when the index is equal to the size of the string. We
// want to catch this exception so it doesn't crash our program...
try {
// Print to the display console for User to enter his/her name...
System.out.println("Enter your name");
// Read what the User supplied and place the text into our 'str'
// String variable...
str=in.readLine();
// Add (append) the string "\nThis is example for string Buffer class
// and its function" to the 'str' string variable. The '\n' is a output
// string tag for establishing a new line within the displayed output.
// the '+=' attached to our 'str' variable is a Assignment Operator. It
// tells the compiler to adds the right operand to the left operand and
// assign the result to left operand. It is the same as writing:
// str = str + "\nThis is example for string Buffer class and its function";
str+="\nThis is example for string Buffer class and its function";
// Establish a String Buffer and name it 'strbuf. A StringBuffer is a
// thread-safe, mutable sequence of characters. A string buffer is like a
// String, but can be modified...
StringBuffer strbuf=new StringBuffer();
// Place our current string held within the 'str' string variable into our
// new String Buffer (strbuf). The StringBuffer.append() method is used for
// this...
strbuf.append(str);
// Print the contents within out string buffer (strbuf) to the display
// console...
System.out.println(strbuf);
// Now Delete (clear) everything within our String Buffer variable (strbuf).
// This is done using the StringBuffer.delete() method. 0 indicates the starting
// point index for the number of characters within the string we want to delete.
// The 'str.length()' portion indicates the ending index point to delete. The
// 'str.length()' method always returns the length of (number of characters) within
// the string variable (str). So, we know our string variable 'str' contains:
// the User provided name, let's say: "Vikraman" plus "\nThis is example for string
// Buffer class and its function" which in total is 66 characters in length but
// because indexing always starts from 0 the length of the string (str) is 65. Our
// line below could be written strbuff.delete(0, 65). Delete characters within the
// string buffer variable (strbuf) starting from index 0 (the first character) to
// index 65 (the last character).
strbuf.delete(0,str.length());
....................................
....................................
........ You Do The Rest .........
....................................
....................................
}
catch(StringIndexOutOfBoundsException e) {
// Display the exception message to console.
System.out.println(e.getMessage());
}
Yes...The comments are excessive and archaic but by the time you are done with it you will be a professional with that piece of code. ;)

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.

Scanner input from InputStream

I'm doing test driven development which requires me to write a test function for a class that takes input from the user. Since the console input function stops for input during tests, I wrote the tests using an InputStream which uses a string.
String str="3\n2\n1\n4\n";
InputStream is = new ByteArrayInputStream(str.getBytes());
assertTrue(app.RunApp(is));
This leads to the calling of the function getChoice(InputStream i) which involves console input from a Scanner.
public int getChoice(InputStream i) throws IOException {
Scanner s=new Scanner(i);
s.useDelimiter("\n");
String y= s.next();
int x=Integer.parseInt(y);
return x;
}
I want the above code to take the numbers in the string one by one. But, what is happening is that it takes the first number properly and then, the position of the stream goes directly to the end of the stream which causes a NoSuchElementException. Please Help!
Use...
String y = s.nextLine(); // That will take the entire line instead of only 1st word

Categories