Java using scanner with try-with-resources - java

I have two versions of Java code that gets user input until user types "q"
Version 1:
public class Test {
public static void main(String[] args) {
String input = "";
while (!input.equals("q")) {
Scanner scanner = new Scanner(System.in);
System.out.print("Input: ");
input = scanner.nextLine();
System.out.println("Input was: " + input);
}
}
}
Version 2:
public class Test {
public static void main(String[] args) {
String input = "";
while (!input.equals("q")) {
try(Scanner scanner = new Scanner(System.in)){
System.out.print("Input: ");
input = scanner.nextLine();
System.out.println("Input was: " + input);
}
}
}
}
Version 1 works as expected but version 2 does not work as expected.
That is after reading user input for the first time, it produces an error
Input: 12
Input was: 12Exception in thread "main"
Input: java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1540)
at RealEstateCompany.main(RealEstateCompany.java:115)
My guess is since version 2 uses try with resource so it closes the scanner after being used and that is causing an error?
Thank you for your help in advance!
[Update]
Version 3:
public class Test {
public static void main(String[] args) {
String input = "";
try(Scanner scanner = new Scanner(System.in)){
while (!input.equals("q")) {
System.out.print("Input: ");
input = scanner.nextLine();
System.out.println("Input was: " + input);
}
}
}
}
Version 3 works. However, why version 3 is ok and version 2 is not ok?

Adding a little bit more detail to my comments
A try-with block is defined as follows:
try(...) {
...
}
where the argument in parenthesis needs to be an instance of java.lang.AutoCloseable. An example is the class java.io.InputStream, which is also the class for System.in.
A try-with attempts to automatically close its provided resource, once the block is left. Depending on the used resource, it closes all its own child resources as well.
Taking your example, you have try(Scanner scanner = new Scanner(System.in)), which uses Scanner as resource. The scanner itself uses System.in as resource. Once the try block is left (when } is reached) it tries to close its resources, which is the Scanner instance. This instance also tries to close its resource, the System.in.
Once System.in is closed, you can't get any input from the console anymore (at least not with some additional work, I think...).
Concretely, in your second example:
while (!input.equals("q")) {
try(Scanner scanner = new Scanner(System.in)){
...
} // <--- The block is left, scanner is closed, System.in is closed
} // <-- start a new iteration
Here after just one iteration, System.in gets closed. Sure, you create a new Scanner in the next iteration, but System.in remains closed, that's why you get your exception in this case.
Your third example:
try(Scanner scanner = new Scanner(System.in)){
while (!input.equals("q")) {
...
} // <-- start a new iteration, while still in the same try block
} // <-- only after the while, your resources are closed
Here you're looping your while, while still being inside try. So no resource gets closed, until you leave while and try. That means, the one Scanner remains intact and with it the one System.in. This allows you to keep reading from the console until you're done looping.

Try this:
String input = "";
try (Scanner scanner = new Scanner(System.in)) {
while (!input.equals("q")) {
System.out.print("Input: ");
input = scanner.nextLine();
System.out.println("Input was: " + input);
}
}
You can use every class thats implements Closeable or AutoCloseable in try-with-resources, When code reaches the end of the try call, It call close() function of the Scanner class in our example.

i run some tests and add the catch block into your code.here's the code
public static void main(String[] args) {
String input = "";
while (!input.equals("q")) {
try(Scanner scanner = new Scanner(System.in)){
System.out.print("Input: ");
input = scanner.nextLine();
System.out.println("Input was: " + input);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
when add the catch block,there are 2 kinds of results
1,only inputs q, works as expected
2,inputs any other String, exception
Input: java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1585)
at rews.pub.Test.main(Test.java:11)
when added the catch block, we will see that the program won't stop, because of the while loop
here is another easier test
public class Test {
public static void main(String[] args) {
String input = "";
Scanner scanner = new Scanner(System.in);
System.out.println("inout--1---");
input = scanner.nextLine();
scanner.close();
Scanner scanner2 = new Scanner(System.in);
System.out.println("inout--2---");
input = scanner2.nextLine();
scanner2.close();
}
}
and it goes same exception
inout--1---
11
inout--2---
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1585)
at rews.pub.Test.main(Test.java:15)
here's my opinion.
in the end of first run, try()block will close the resource which is in the block, means we close the system.in
system.in is a object of inputSteam,and system.in is final and static, we can't open it again like 'new Scanner(System.in)'

Related

Scanner issue! Code is skipping the first user input and printing twice instead of once ONLY on the first iteration

https://courses.cs.washington.edu/courses/cse142/15sp/homework/6/spec.pdf
EDIT* Input Files are here:(sorry i'm new to stack overflow, hopefully this works)
I've also tried console.next() but it gives different errors than console.nextLine() in the rePlaceholder method. **
tarzan.txt - https://pastebin.com/XDxnXYsM
output for tarzan should look like this: https://courses.cs.washington.edu/courses/cse142/17au/homework/madlibs/expected_output_1.txt
simple.txt https://pastebin.com/Djc2R0Vz
clothes.txt https://pastebin.com/SQB8Q7Y8
this code should print to an output file you name.
Hello, I have a question about scanners because I don't understand why the code
is skipping the user input on the first iteration but works fine on the rest.
I'm writing a code to create a madlib program and the link will provide the explanation to the program but pretty much you have these placeholders in a text file and when you see one, you prompt for user input to replace it with your own words. However, my program always go through TWO placeholders first and only ask the user input for one, completely skipping the first placeholder. What is wrong with my code??? Also, how do you fix this? Everything else is running perfectly fine, only that the first line is consuming two placeholders so I'm always off by one.
Welcome to the game of Mad Libs.
I will ask you to provide various words
and phrases to fill in a story.
The result will be written to an output file.
(C)reate mad-lib, (V)iew mad-lib, (Q)uit? c
Input file name: tarzan.txt
Output file name: test.txt
Please type an adjective: Please type a plural noun: DD DDDD <--- why is it like this
Please type a noun: DDDD
Please type an adjective: DD
Please type a place:
========================================================================
package MadLibs;
import java.util.*;
import java.io.*;
public class MadLibs2 {
public static void main(String[] args) throws FileNotFoundException {
Scanner console = new Scanner(System.in);
intro();
boolean isTrue = true;
while(isTrue) {
System.out.print("(C)reate mad-lib, (V)iew mad-lib, (Q)uit? ");
String choice = console.next();
if (choice.equalsIgnoreCase("c")) {
create(console);
}
else if (choice.equalsIgnoreCase("v")) {
view(console);
}
else if (choice.equalsIgnoreCase("q")) {
System.exit(0);
}
}
}
public static void view(Scanner console) throws FileNotFoundException {
System.out.print("Input file name: ");
String viewFile = console.next();
File existingMadLib = new File(viewFile);
Scanner printText = new Scanner(existingMadLib);
while(printText.hasNextLine()) {
System.out.println(printText.nextLine());
}
}
public static void create(Scanner console) throws FileNotFoundException {
System.out.print("Input file name: ");
String inputFile = console.next();
File newMadLib = new File(inputFile);
while(!newMadLib.exists()) {
System.out.print("File not found. Try again: ");
inputFile = console.next();
newMadLib = new File(inputFile);
}
System.out.print("Output file name: ");
String outputFile = console.next();
System.out.println();
PrintStream output = new PrintStream(new File(outputFile));
Scanner input = new Scanner(newMadLib);
while(input.hasNextLine()) {
String line = input.nextLine();
outputLines(line, output, console);
}
}
public static void outputLines(String line, PrintStream output, Scanner console) throws FileNotFoundException{
String s = "";
Scanner lineScan = new Scanner(line);
while(lineScan.hasNext()){
s = lineScan.next();
if(s.startsWith("<") || s.endsWith(">")) {
s = rePlaceholder(console, lineScan, s);
}
output.print(s + " ");
}
output.println();
}
public static String rePlaceholder(Scanner console, Scanner input, String token) {
String placeholder = token;
placeholder = placeholder.replace("<", "").replace(">", "").replace("-", " ");
if (placeholder.startsWith("a") || placeholder.startsWith("e") || placeholder.startsWith("i")
|| placeholder.startsWith("o") || placeholder.startsWith("u")) {
System.out.print("Please type an " + placeholder + ": ");
} else {
System.out.print("Please type a " + placeholder + ": ");
}
String change = console.nextLine();
return change;
}
public static void intro() {
System.out.println("Welcome to the game of Mad Libs.");
System.out.println("I will ask you to provide various words");
System.out.println("and phrases to fill in a story.");
System.out.println("The result will be written to an output file.");
}
}
in your rePlaceholder, change this line:
String change = console.nextLine();
Into this
String change = console.next();
Your problem is that nextLine doesn't wait for your output, just reads what it has in the console, waiting for a new line.
This is from the documentation to be a bit more precise on the explanation:
Since this method continues to search through the input looking for a
line separator, it may buffer all of the input searching for the line
to skip if no line separators are present.
UPDATE
After reading the comment, the previous solution will not work for multiple words.
After reading the output file, you are using next().
You need to make another call to nextLine() to clean the buffer of any newlines.
System.out.print("Output file name: ");
String outputFile = console.next();
console.nextLine(); // dummy call
System.out.println();

Java: try(Scanner scan = new Scanner(System.in) { } causing an exception

Using try(Scanner scan = new Scanner(System.in)) { } is causing
Exception in thread "main" java.util.NoSuchElementException
When I try to debug it says that
Variable information not available, source compiled without -g option.
and shows the below code
public Scanner(InputStream source) {
this(new InputStreamReader(source), WHITESPACE_PATTERN);
}
One of my methods that uses this line:
protected String loginName(){
String username;
String password;
try (Scanner scan = new Scanner(System.in)) { // This line is causing the error.
System.out.print("Enter Username: ");
username = scan.next();
System.out.print("Enter Password: ");
password = scan.next();
}
if(getUsernamesList().contains(username))
if(password.equals(getPasswordsList().get(getUsernamesList().indexOf(username)))) return username;
else return "-1";
else return "-1";
}
You're closing System.in (a global-variable). Please, do not do that. Everywhere you have
try(Scanner scan = new Scanner(System.in))
guarantees that System.in will be close(d). Once it's close(d) you can't read from it again (or you get your mentioned Exception). Also, you can compile with debug symbols (or step into it with your IDE's built-in debugger or jdb as applicable). The Scanner.close() Javadoc says (in part),
If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close method will be invoked
Have you tried not using the try?
String username;
String password;
Scanner scan = new Scanner(System.in);
System.out.print("Enter Username: ");

NoSuchElement using scanner

I have declared two strings and reading the input using Scanner(System.in).
After this when i am closing the Scanner and again reading the another input using the Scanner,then it throws an error: NoSuchElementException.
Please guide me on this
import java.util.Scanner;
import java.io.*;
public class NumericInput
{
public static void main(String[] args)
{
// Declarations
Scanner in = new Scanner(System.in);
String string1;
String string2;
// Prompts
System.out.println("Enter the value of the First String .");
// Read in values
string1 = in.nextLine();
// When i am commenting below line(in.close) code is working properly.
in.close();
Scanner sc = new Scanner(System.in);
System.out.println("Now enter another value.");
string2 = sc.next();
sc.close();
System.out.println("Here is what you entered: ");
System.out.println(string1 + " and " + string2);
}
}
When you close your scanner it also closes System.in input stream, you are using it again, but it's closed, so when you try to use Scanner again, no open System.in stream is found.
There is no need to close a Scanner, since it implements AutoCloseable interface you should declare resources in try-with-resources as of java 7. If closing Scanner is an issue.
try(Scanner in = new Scanner(System.in); Scanner sc = new Scanner(System.in)){
// do stuff here without closing
}
catch(Exception){
e.printStackTrace();
}

Odd error related to Stream being closed

I am learning Java and I wrote a method to update a record in a file. The problem I am having is when I ask the user if they would like to look for another file my reader is closed or is unable to assign any input to it.
protected boolean Update() throws InputMismatchException
{
RoomService Init =new RoomService();
Scanner input = new Scanner(System.in);
try {
boolean ans= true;
while(ans)
{
System.out.println("Please enter room number.");
String id = input.next();
Init.Update(id);
System.out.println("Press Enter to Add more or no to exit");
String choice = input.nextLine();// Skips this line
if (choice.equalsIgnoreCase(""))
{
continue;
}
else if(choice.equalsIgnoreCase("no"))
{
ans= false;
}
else
{
System.err.println("Wrong input");
throw new IOException();
}
}
} catch (IOException e) {
e.printStackTrace();
fail=true;
}
return fail;
}
Wondering what exactly is blocking me from entering anything I also used BufferedReader input = new BufferedReader(new InputStreamReader (System.in))
Thanks.
Edit:
Using Scanner Error is : java.util.NoSuchElementException
Using BufferedReader error is: java.io.IOException: Stream closed
If there is anywhere else in your code you are using a Scanner wrapped around System.in, make sure you do not call close() on it. A Scanner itself has no resources that need to be closed, unless you want to close the underlying input source, which for a Scanner wrapped around System.in, you don't, because that prevents all future input.

System.console() gives a NullPointerException in NetBeans

I have the following problem: method readLine() or nextLine(), nextInt(), etc. throw an exception: NullPointerException.
I use the NetBeans IDE (if it matters).
public static void Reading()
{
String qq;
qq = System.console().readLine();
System.console().printf(qq);
}
Some IDEs don't provide a console. Note that System.console() returns null in these cases.
From the documentanion
Returns:
The system console, if any, otherwise null.
You can always use System.in and System.out instead, as follows:
String qq;
Scanner scanner = new Scanner(System.in);
qq = scanner.nextLine();
System.out.println(qq);
Two things:
The standard way of printing things is System.out.println("Thing to print");
The standard way of reading input off the console is: Scanner s = new Scanner(System.in); String input = s.nextLine();
So with these in mind, your code should be
public static void Reading() {
String qq;
Scanner s = new Scanner(System.in);
qq = s.nextLine();
System.out.println(qq);
s.close();
}
or
public static void Reading() {
String qq;
try (Scanner s = new Scanner(System.in)) {
qq = s.nextLine();
System.out.println(qq);
}
}

Categories

Resources