package sandbox2;
import java.util.Scanner;
public class Sandbox2
{
public static void main(String[] args)
{
for (int i = 0; i < 5; i++)
{
String s = askForProperty("Enter value for " + i + ": ");
System.out.println(i + " is: " + s);
}
}
private static String askForProperty(String message)
{
Scanner keyboard = new Scanner(System.in);
System.out.print(message);
String s = keyboard.nextLine();
keyboard.close();
return s;
}
}
When i run the above code, it returns the first response PERFECTLY. When it tries to ask for the second response, it returns:
java.util.NoSuchElementException: No line found
Why would it return this error? Each time the method askForProperty is called, the Scanner is a completely new instance! Does it have something to do with System.in as an input stream?
Define your scanner as a class variable and then close it only after you are done with all iterations. In your current setup, when you call keyboard.close you are also closing System.in which makes it unusable later on.
package sandbox2;
import java.util.Scanner;
public class Sandbox2 {
static Scanner keyboard = new Scanner(System.in); // One instance, available to all methods
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
String s = askForProperty("Enter value for " + i + ": ");
System.out.println(i + " is: " + s);
}
keyboard.close(); //Only close after everything is done.
}
private static String askForProperty(String message) {
System.out.print(message);
String s = keyboard.nextLine();
return s;
}
}
Closing a Scanner causes the underlying InputStream to be closed also. As there is only one System.in, any newly created Scanner objects will not be able to read from the same stream:
keyboard.close();
Close the Scanner in the last.
So,
The chief problem in your code is that you create and close Scanner immediately in every single iteration. That simply does not work. Imagine Scanner as a large connection to your IO that requires quite some assemblage. If you open / close it every single time - You might just find a case where the next command is fired before the connection is opened once again. It's very similar to what you might find in a DB connection as well. The way to prevent it is to have Scanner open BEFORE you start iterating, finish the loop and then close it.
Hence, remove the close() statement from the askForProperty() function and move it to your main. Pass the Scanner keyboard object to the function. Once all the iterations are over - Then close it.
import java.util.Scanner;
public class Sandbox2
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in); // Initialize the Scanner
for (int i = 0; i < 5; i++)
{
String s = askForProperty("Enter value for " + i + ": ", keyboard); // Pass the Scanner
System.out.println(i + " is: " + s);
}
keyboard.close(); // Close the Scanner now that the work is done.
}
private static String askForProperty(String message, Scanner keyboard)
{
System.out.println(message);
String s = keyboard.nextLine();
return s;
}
}
Related
I am supposed to make a program that asks users for a list of input. Then, from that list, my program is supposed to pick out the third answer and then print it out. It sounds really simple, but how do I assign numbers to each of the user inputs? Do I even do that? I am a beginner, and thank you so much for your help!
This is the code I have so far:
import java.util.*;
public class MyProgram
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
while(true) {
System.out.println("What do you appreciate in your life or school?");
String ans = scan.nextLine();
if(ans.equals(""))
{
break;
}
}
System.out.println("You said \"" + input3 + "\" as your third answer.");
}
}
You can strore the third input in a variable you initialized bevor the loop.
if there is no third input it prints: ""
import java.util.*;
public class MyProgram
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
int index = 0;
String input3 = "";
while(true) {
System.out.println("What do you appreciate in your life or school?");
String ans = scan.nextLine();
if (index == 2) {
input3 = ans;
}
if(ans.equals("")){
break;
}
index++;
}
System.out.println("You said \"" + input3 + "\" as your third answer.");
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a console application with a main method and some methods that I call from main. There, I want to ask the user for some input, for which I use the Scanner class.
Here's my problem:
I find there is no way to use Scanner when reading inputs from outside main without random exceptions or unexpected behaviour. I have tried two approaches:
Having a Scanner global variable in the class containing main. Then
I use this same Scanner in all functions in that same class.
In every function I need to ask for input, I declare a new Scanner
variable, use it, and close it before exiting the function.
1. makes Scanner try to read twice. I mean, I have a sc.readLine in a function and, when I exit that function, I have another sc.readLine in main. I input once and the two readLine lines get executed, the second one reading an empty String.
2. throws Exception (base class Exception) when I call any sc.readLine for a second time during the execution of the program.
I have also noticed that any other method other than readLine is going to read various items on the same line. For example, line "10 20 30 40" would execute 4 sc.nextInt calls.
TL;DR: how do you use Scanner in a console application?
One way:
import java.util.Scanner;
public class Main {
private Scanner scanner = new Scanner(System.in);
public Scanner getScanner() {
return scanner;
}
void fun1() {
Scanner in = getScanner();
System.out.print("Enter a string: ");
System.out.println("You entered: " + in.nextLine());
}
void fun2() {
Scanner in = getScanner();
System.out.print("Enter an integer: ");
int n = 0;
try {
n = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
e.printStackTrace();
}
System.out.println(n + " + 10 = " + (n + 10));
}
public static void main(String[] args) {
Main m = new Main();
m.fun1();
m.fun2();
}
}
A sample run:
Enter a string: Hello world!
You entered: Hello world!
Enter an integer: 25
25 + 10 = 35
Another way:
import java.util.Scanner;
public class Main {
static void fun1(Scanner in) {
System.out.print("Enter a string: ");
System.out.println("You entered: " + in.nextLine());
}
static void fun2(Scanner in) {
System.out.print("Enter an integer: ");
int n = 0;
try {
n = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
e.printStackTrace();
}
System.out.println(n + " + 10 = " + (n + 10));
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
fun1(in);
fun2(in);
}
}
A sample run:
Enter a string: Hello world!
You entered: Hello world!
Enter an integer: 25
25 + 10 = 35
Regarding your problem with next() or nextInt(): Given below is the recommended way for multiple inputs in one go.
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
boolean valid = true;
System.out.print("Enter some intgers: ");
String strNum = in.nextLine();
String[] strNumArr = strNum.split("\\s+");
int[] numArr = new int[strNumArr.length];
for (int i = 0; i < strNumArr.length; i++) {
try {
numArr[i] = Integer.parseInt(strNumArr[i]);
} catch (NumberFormatException e) {
numArr[i] = Integer.MIN_VALUE;
valid = false;
}
}
System.out.println(Arrays.toString(numArr));
if (!valid) {
System.out.println("Note: invalid inputs have been reset to " + Integer.MIN_VALUE);
}
}
}
A sample run:
Enter some intgers: 10 5 20 15
[10, 5, 20, 15]
Another sample run:
Enter some intgers: 4 40 a 20 b 15
[4, 40, -2147483648, 20, -2147483648, 15]
Note: invalid inputs have been reset to -2147483648
Check Scanner is skipping nextLine() after using next() or nextFoo()? for more information about console input using Scanner.
to use a single instance of Scanner (or any other datatype or class), you can use the design pattern "Singleton" which consist to instantiate a single instance of your Object for the whole project.
The Singleton definition (a new class) :
import java.util.Scanner;
public class ScannerSingleton {
private static Scanner sc = null;
private ScannerSingleton() {
sc = new Scanner(System.in);
}
public static Scanner getInstance() {
if (sc == null) {
synchronized(ScannerSingleton.class) {
if (sc == null)
sc = new ScannerSingleton();
}
}
}
}
and each time you want to use your scanner anywhere you only have to call ScannerSingleton.getInstance() which will return your single instance of scanner
example of use:
String test = ScannerSingleton.getInstance().nextLine();
I suggest to pass your Scanner object as another parameter for your functions.
public static void main(String[] args)
{
Scanner scanner=new Scanner(System.in);
String answer = ask(scanner, "what is your name?");
System.out.println("Oh! Hello dear " + answer + "!");
scanner.close();
}
private static String ask(Scanner scanner, String question)
{
System.out.println(question);
return scanner.nextLine();
}
Program to count how many times a particular character, letter or number occur in a sentence.
However I keep getting message:
Resource leak: 'sc' is never closed
I am using Java and Eclipse. What should I do?
import java.util.Scanner;
class Number-count {
public static void number - count(String args[]) {
String s;
char ch;
int count = 0;
Scanner SC = new Scanner(System. in );
System.out.println("Enter a sentence");
String str = sc.nextLine();
System.out.println("Enter a character to be searched for occurence");
s = sc.nextLine();
char c = s.charAt(0);
for (int i = 0; i < str.length(); i++) {
ch = str.charAt(i);
if (ch == c) {
count++;
}
}
System.out.println("Character " + c + " occur " + count + " times");
}
}
Scanner objects need to be closed after one is done using them. So, after you're done with it you should call the following before the end of your main method
SC.close();
after your scanner work completed put: sc.close();
It is working 100%
Try this code
public static void number - count(String args[]) throws IOException {
Scanner sc = new Scanner(System.in);
try{
//your code
}
finally {
sc.close();
}
}
If you want to use the scanner globally in a class(which is the case sometimes)
try this:
static Scanner sc = new Scanner(System.in);
/* Making it easy for beginners, when we use Scanner sc it is required to be close once we have taken all inputs from user, to close use sc.close(); */
package basicjava;
import java.util.*;
public class sumbyuser {
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
System.out.println("Enter your numbers for summation : ");
int a = sc.nextInt();
int b = sc.nextInt();
sc.close();
int sum = a+b;
System.out.println("Summation is : "+sum);
}
}
Try sc.close();
After the using the scanner inputs :
import java.util.*;
public class Func1 {
public static void CalculateSum() {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
sc.close();
int sum = a + b;
System.out.println("The sum is " + sum);
}
public static void main(String[] args) {
CalculateSum();
}
}
heres what i got, take a look and see what you can find. eclipse says everything is good to go, but when i run it, i get to input the 5 numbers, then it asks the two lines about highest to lowest or vice versa, then crash before i can put my answer in. im at a loss.
these are the errorrs i see. Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:907)
at java.util.Scanner.next(Scanner.java:1416)
at monty.intarray.main(intarray.java:25)
import java.util.Arrays;
import java.util.Scanner;
public class intarray {
public static void main(String[] args) {
System.out.println("Enter a number other than zero, then hit enter. Do this five times.");
Scanner input1 = new Scanner(System.in);
int[] array=new int[5];
for (int whatever = 0; whatever < array.length;whatever++)
array[whatever]=input1.nextInt();
input1.close();
System.out.println("Now tell me if you want to see those numbers sorted from lowest to highest, or highest to lowest.");
System.out.println("Use the command 'lowest' without the single quotes or 'highest'.");
Scanner input2 = new Scanner (System.in);
String answer = input2.next();
input2.close();
boolean finish;
finish = loworhigh(answer);
if (finish) {
Arrays.sort(array);
for (int a = array.length - 1; a >= 0; a--) {
System.out.print(array[a] + " ");
}
}
else {
Arrays.sort(array);
for (int b=0; b<=array.length; b++) {
System.out.print(array[b] + " ");
}
}
System.out.print(array[0] + ", ");
System.out.print(array[1] + ", ");
System.out.print(array[2] + ", ");
System.out.print(array[3] + ", ");
System.out.print(array[4] + ".");
}
public static boolean loworhigh(String ans) {
if (ans.equalsIgnoreCase("lowest")) return false;
else return true;
}
}
When you call on for input1.close, it also closes System.In input stream along with the scanner.
To check if Scanner is still available you can try:
System.out.println(System.in.available());
And there is no way to re-open System.In
public void close() throws IOException --> Closes this input stream and releases any system resources associated with this stream. The general contract of close is that it closes the input stream. A closed stream cannot perform input operations and **cannot be reopened.**
And thus it throws NoSuchElementException
To avoid this, don't close input1 and instead use the same Scanner object and accept as many inputs as required and finally close the Scanner.
Hope this helps.
So as you may be able to tell from my attempt, I'm trying to figure out how I'd make a program which gives the user 5 seconds to enter some lines of text, then the Scanner will count how many lines were entered. I've just started learning Java as my 2nd language, so please try to explain everything as simply as possible :)
I've got two theories as to why it's not working. The first is that nextLine() will return the whole line, regardless of whether it's empty or not meaning rather than NL equaling "", it will actually equal the whole line (ie " "). And my second theory is that I've got no idea what I'm doing and the program flow is all over the place. Anyway, here's my code:
class OrigClass{
public static void main(String args[]){
Scanner ScanObj = new Scanner(System.in);
int Count = 0;
String NL = ScanObj.nextLine();
try{
Thread.sleep(5000);}
catch (InterruptedException e){
e.printStackTrace();
}
while (!NL.equals("")){
Count++;
NL = ScanObj.nextLine();
}
System.out.print("You Entered " + Count + " Lines.");
ScanObj.close();
}
}
Oh, I forgot to mention hasNext() was what I originally tried:
import java.util.Scanner;
class OrigClass{
public static void main(String args[]){
Scanner ScanObj = new Scanner(System.in);
int Count = 0;
try{
Thread.sleep(5000);}
catch (InterruptedException e){
e.printStackTrace();
}
while (ScanObj.hasNext() == true){
Count++;
ScanObj.nextLine();
}
System.out.print("You Entered " + Count + " Lines.");
ScanObj.close();
}
}
From the looks of it, this code should work. My only guess is that you are manually entering the input and are forgetting to signal the end of input with CTRL+D. However, doing this, you'll get a NoSuchElementException if you do not use ScanObj.hasNext().
You could also run your code using input redirection. java OrigClass < data
A better way to do this would be the following:
import java.util.Scanner;
public class Sc {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int count = 0;
String nl; // = scan.nextLine();
//while (!NL.equals(""))
while(scan.hasNext())
{
count++;
nl = scan.nextLine();
}
System.out.println("Done! Count: " + count);
scan.close();
}
}
The difference here is that we save the first nextLine() until we're in the while loop. This will give an accurate count of how many lines are in the input.
Just don't forget to signal end of input with CTRL+D.
Well this solution is not really good. but works.
public class FiveSecond {
public static void main(String args[]){
new Thread(new Count(new Reader())).start();
}
}
class Count implements Runnable{
Reader r;Thread t;
Robot ro;
public Count(Reader t){this.r=t;
try {
ro=new Robot();
} catch (AWTException e) {e.printStackTrace();}
}
#Override
public void run() {
t=new Thread(r);
//t.setDaemon(true); //[S2]
t.start();
try{
Thread.sleep(5000);
}catch(Exception e){}
t.interrupt();
//Implicitly press the enter key in order to release the readLine() method :D
//not recommended, and it's not a good idea, but works
ro.keyPress(KeyEvent.VK_ENTER);
ro.keyRelease(KeyEvent.VK_ENTER);
/*
* this is possible to save the strings lines in somewhere in order to access from invoker application
* or send back the strings by socket, etc . . .
*/
System.out.println("number of entered lines "+r.getCount()+"\n");
//you would run this main as a process and get the number of counts
//System.exit(r.getCount()); //[S2]
}
}
class Reader implements Runnable{
private List<String> lines;
private volatile int count;
private BufferedReader br;
public Reader(){
lines=new ArrayList<String>();
br=new BufferedReader(new InputStreamReader(System.in));
}
#Override
public void run() {
try{String line;
System.out.println("you have 5 second to detect a 2048 length character, then your system will broken");
while((line=br.readLine())!=null){
if(!Thread.currentThread().isInterrupted()){
count++;lines.add(line);}else{break;}
}
//for showing the lines entered
//System.out.println(lines.toString());
}catch(Exception ex){}
}
public int getCount(){return this.count;}
}
but the best approach is about running a separated process to count the lines, and you would just remove the [S2] comments to achieve it.