close() closes input streams permanently - java

I am trying to make a simple method readIn() that reads something in from System.in. (Can't use Console because System.console() returns null when I run in Eclipse). The idea is to call readIn as needed, like this
classs Foo{
public static void(String[] arg){
String first = readIn("First, please");
System.out.println(first);
String second = readIn("Second, please");
System.out.println(second);
}
}
Here is the simplest form of readIn():
static String readIn(String prompt){
System.out.println(prompt + ": ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
br.close(); // PROBLEM STATEMENT
return line;
}
If I omit the br.close() statement it works fine - I can call readIn repeatedly. But if I close br, as I should, then only the first call works. Second call throws IOException: Stream closed. As expected, the same thing happens with try-with-resources in readIn:
static String readIn(String prompt){
System.out.println(prompt + ": ");
String line;
try(
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)) )
{
line = br.readLine();
}
return line;
}
Same thing happens with Scanner(System.in) instead of BufferedReader. It does not happen when reading from files.
Which stream is closed if a new BufferedReader or Scanner is made in every call to readIn? Is this something about close() closing the "underlying Readable/Closeable" (System.in)? Can it be reopened? Trying to understand, thanks.

br.close(); closes also system input stream System.in, so you can't use it unless you restart JVM.
You can use the same BufferedReader instance for all required input from System.in
Don't be shy also to mix calls:
System.out.println
br.readLine();
They are related to different streams, so there shouldn't be any issues.

Related

How EXACTLY does the Scanner class interact with the fileReader in the following code?

try{
PrintWriter pW = new PrintWriter("newFile.txt");
pW.println("Hello");
pW.print("My name is Julian");
pW.println("");
pW.print("This is the third line");
pW.close();
FileReader fR = new FileReader("newFile.txt");
Scanner scan = new Scanner(fR);
System.out.println(scan.nextLine());
System.out.println(scan.nextLine());
System.out.println(scan.nextLine());
}catch(Exception ex){
}
Thus far, I have understood that a fileReader object can use the "read" method to read data from a file into an array of characters.
However, in the above code, the Scanner object takes the fileReader object as an argument to its constructor. What is going on "under the hood" so to speak when the statement System.out.println(scan.nextLine()); is executed? How does the Scanner object "obtain" data from the fileReader object?
To conceptualize whats going on "under the hood" I imagine the Scanner object's buffer is similar to an array. Thus, what will happen under the hood is essentially the fileReader object's read method will be called, and the argument passed will be the Scanner objects buffer(something like fileReaderobject.read(Scannerobject.Scannerobjectbuffer) . Thus, the data from the file will be read into Scanner objects buffer, and we can use the next/nextLine methods to obtain this data. Is this a somewhat correct way of conceptualizing what is happening under the hood?
FileReader is just a Reader, so Scanner likely uses the read() method to read a line. Something like this:
Reader reader = ... (FileReader..);
public String nextLine() {
StringBuffer sb = new StringBuilder();
int c;
while( (c = reader.read() ) != -1 && c != '\n' )
sb.append( (char)c );
return sb.toString();
}

try with resources closing the resources unexpectedly

I am trying to invoke the following method inside a while loop. First time, it invokes fine but on 2nd loop execution, it throws an IOException
public String getInputString(String prompt){
System.out.print(prompt);
String inputLine = null;
try(BufferedReader br = new BufferedReader(new InputStreamReader(System.in))){
inputLine = br.readLine();
if(inputLine.length() == 0){
return null;
}
}
catch(IOException e){
e.printStackTrace();
}
return inputLine;
}
I am getting this IOException:
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
at java.io.BufferedInputStream.read(BufferedInputStream.java:325)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at ch5.GameHelper.getInputString(GameHelper.java:14)
at ch5.SimpleDotComTestDrive.main(SimpleDotComTestDrive.java:19)
On the other hand, it is working fine when i try to execute it as follows:
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
inputLine = br.readLine();
if(inputLine.length() == 0){
return null;
}
}
catch(IOException e){
e.printStackTrace();
}
What is the reason for such a behaviour?
I suspect you're calling getInputString more than once.
The first time, it should work fine - but then you're closing System.in (by closing the BufferedReader wrapping InputStreamReader wrapping System.in)... which means the next time you try to read from System.in, you won't be able to.
If you remove the try-with-resources statement, you could still have problems, because you'll be creating multiple readers around the same stream - if one of those reads more input than you actually use, it won't be available later on.
I suggest you create a BufferedReader wrapping an InputStreamReader wrapping System.in once, at the start of your program, and use that BufferedReader instance everywhere.

Faster input style in java

Scanner has a method hasNext() but if i want to use BufferedReader insteadOf Scanner how to handle hasNext() types of method in BufferedReader?
I want to do this because BufferedReader is faster than Scanner. Is there any faster input reading way besides BufferedReader?
Need Help! Thanks in advance.
If you are working with Strings use a StringBuilder. It is a built in object in Java and allows you to not have to recreate a String every time you append a String.
I have not worked with a scanner much because I like BufferedReader so much. Java's BufferedReader reads a certain amount of bytes at a time. The default buffer size is 8192 characters. You can change this is you want to if you think you will be reading enormous amounts of characters. An integer as the second parameter would specify the number of bytes to read each time.
This is how you would use a BufferedReader and StringBuilder efficiently:
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
String output;
try(BufferedReader reader = new BufferedReader(new FileReader(System.getProperty("user.home") + "/Desktop/lotsOfText.txt"), 8192)) { //if you want a bigger buffer - give it a larger number
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n"); //StringBuilder returns a reference to itself
}
} catch (IOException io) {
System.err.println(io.toString());
}
output = sb.toString();
System.out.println(output);
}
If you are expecting double or ints, you can use a try{}catch (Exception e){} and in the try use either java's class Double or Integer to parse a string:
try {
double d = Double.parse(line);
int i = Integer.parse(line);
catch (NumberFormatException nfe) {
System.err.println(nfe.toString() + "\n\nThe number was unreadable");
}
Your question was really vague, so it is hard to give you an explicit answer. I hope this helps.
Also, as a note, BufferedReader also accepts an InputStreamReader as an argument, so you could have
try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)) {} catch...
in order to read user input.
The "truly" correct way to read an InputStream can be found here

ReadLine - execute twice?

I need to be able to read each line of the file for multiple arguments, hence the for loop. After the first one, it does not seem to be reading them anymore, seems to skip the try statement. Any ideas? I'm sure Its something silly I am missing but have been playing about with it and unfortunately time is not on my side.
for (int j = 0; j < ags.length; j++){
try{
String nameFromFile = null;
BufferedReader InputReader = new BufferedReader(new InputStreamReader(System.in));
while ((nameFromFile = InputReader.readLine()) != null) {
// Do stuff
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
You appear to have two sources you want to compare System.in and args I suggest you read these individually and then compare them.
Set<String> fromInt = new HashSet<>();
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
for(String line; (line = br.readLine()) != null;)
fromIn.add(normalise(line));
}
// compare argsList with fromIn.
e.g.
for(String arg: args) {
if (fromIn.contains(normalise(arg))) {
// something
} else {
// something else
}
}
I need to be able to read each line of the file
What file? You're reading from System.in:
BufferedReader InputReader = new BufferedReader(new InputStreamReader(System.in));
Your code will block at this line until you enter something at the console.
You do not read a file, bu the System.in stream.
Every stream has an internal pointer, so the stream nows, which line was read at last.
If the System stream was read once, the pointer is pointing to the end of the stream.
As long as the stream is not reset, the read command will not return anything.
try
InputStream.reset()
or even better, only read the Stream once and cache the result! This is faster and safe, because the Stream input can change during iteration.
Your code will never exit from while loop.
while ((nameFromFile = InputReader.readLine()) != null)
In above loop it will print only one time and at the end of the file it will not be out of the while loop . That's why you are getting only one time output. Since it is not exited from while loop it does not go back into for loop. readLine() return the string and it is terminated by "\n" or "\r\n". Change as below and you will be able to read as ags.length
while ((nameFromFile = InputReader.readLine())=="\n")

Getting input from user in Console without using Scanner

I would like to know about other ways of getting input from users using other classes like BufferedReader,etc rather than using Scanner class. So, was there any other way of getting input from the user? If so, was it efficient than Scanner class?
if you are using the Java SE6 or higher then you can make use of Console clas
Console console = System.console();
if (console==null){
System.out.print("console not available ");
}else {
String line = console.readLine("Enter name :");
System.out.print("your name :"+line);
}
You can do it simply by the following steps:
Use the BufferedReader Class and wrap it with the InputStreamReader Class.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
//string str = br.readLine(); //for string input
int i = Integer.parseInt(br.readLine()); // for Integer Input
Now since the readLine method throws an IOException you need to catch it. The whole code will look like this:
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
//string str = br.readLine(); //for string input
int i = Integer.parseInt(br.readLine()); // for Integer Input
} catch(IOException ioe) {
ioe.PrintStackTrace();
}
You can use System.in directly, like this:
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = r.readLine()) != null) {
System.out.println(line);
}
Although this may be a little faster than using the Scanner, it's not an apples-to-apples comparison: Scanner provides more methods for tokenizing the input, while BufferedReader can split your input into lines, without tokenizing it.
Use this:
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
to create a reader for System.in, and you can use stdin.readLine() or something to get what you want.
Using a BufferedReader is MUCH more efficient than using a Scanner.
Here for example...
InputStreamReader inStream = new InputStreamReader(System.in);
BufferedReader stdin = new BufferedReader(inStream);
int num , num2;
String str[]=new String[2];
System.out.print("Please Enter Your First Number:");
str[0] = stdin.readLine();
System.out.print("Please Enter Your Second Number:");
str[1] = stdin.readLine();
num = Integer.parseInt(str[0]);
num2 = Integer.parseInt(str[1]);
A user can input data at the time of execution of the program without using a scanner class, and this can be done by using the following program.
class Demo
{
public static void main(String ar[])
{
int ab = Integer.parseInt(ar[0]);
int ba = Integer.parseInt(ar[1]);
int res = ab+ba;
System.out.print(res);
}
}
This is a basic program where a user can input data at the time of execution and get the desired result. You can add, subtract, Multiply, divide and concatenate strings, in CMD and a user can input data after compiling the java program i.e at the time of calling the class file. You just need to call the class file and then enter the data after a space.
C:\Users\Lenovo\Desktop>java Demo 5 2
Here ab= 5 and ba= 2. A user can have any number or string if he wants.

Categories

Resources