Resource leak: 'in' is not closed at this location - java

I just want someone to review my code and suggestion to improve this as a well-written java code.
What I am doing is getting a user input using Scanner, until user input a Number between 0-10.
int Ai = getInput("i", "A");
int Aj = getInput("j", "A");
int Bi = getInput("i", "B");
int Bj = getInput("j", "B");
private static int getInput(String axis, String point) {
int coordinate = 0;
boolean valid = false;
while(!valid){
Scanner in = new Scanner(System.in);
System.out.println("Enter "+ axis +" for " + point +" > ");
if (in.hasNextInt()){
coordinate = in.nextInt();
if (coordinate >= 0 && coordinate <10){
valid = true;
return coordinate;
}
}
}
return coordinate;
}
But I am getting a warning "Resource leak: 'in' is not closed at this location" in line 11 (return coordinate;) Please can someone explain me this

You don't have to instantiate Scanner object in every time the loop runs. So place the Scanner in = new Scanner(System.in); above while loop.
You don't need return inside if block. Because valid = true inside if block which evaluates to false inside while condition which breaks out of loop.
Use this code instead:
private static int getInput(String axis, String point) {
int coordinate = 0;
boolean valid = false;
Scanner in = new Scanner(System.in);
while(!valid)
{
if (in.hasNextInt()){
coordinate = in.nextInt();
if (coordinate >= 0 && coordinate <10){
valid = true;
}
}
}
in.close();
return coordinate;
}
Whenever you open external resources(I/O) in your code in any language( most of them), you have to close that external resource.
Always you have to close the instances of classes that deal with I/O after you are finished with them.
Here the external resource is System.in, you have opened it to take the input but after your work you didn't close that resource. That is why it is asking you to close it.
If you close the scanner in.close() you can't use in to get input next time unless you open it again by instantiating it.
Add the in.close() above both the return statements and there should be no error.
Edit:
The problem is we are closing Scanner in the getinput() which is also closing System.in as said by "Henry" in the comments.
So declare it as static and close the Scanner at the end of the main().
Code:
import java.util.Scanner;
public class Main{
static Scanner in = new Scanner(System.in); //Declared as Static
private static int getInput(String axis, String point) {
int coordinate = 0;
boolean valid = false;
while(!valid)
{
System.out.println("Enter "+ axis +" for " + point +" > ");
if (in.hasNextInt()){
coordinate = in.nextInt();
if (coordinate >= 0 && coordinate <10){
valid = true;
}
}
}
return coordinate;
}
public static void main(String[] args) throws Exception
{
int Ai = getInput("i", "A");
int Aj = getInput("j", "A");
int Bi = getInput("i", "B");
int Bj = getInput("j", "B");
in.close(); // close the scanner when your program is about to end
}
}

when dealing with multiple inputs in a single line
you should use the append the following lines to your code
String[] in= lines.trim().split("\\s+");
for (int i = 0; i < 2; i++) {
a[i] = Integer.parseInt(in[i]);
}
you might not know if a user inputs data in this order the program [earlier] won't be able to parse it causing the function to fail to act properly.

Related

Entering (input/scanner) two same numbers consecutively to break a loop "while" Java

I am a new-bee in java, I have a problem that i cant figure out to compare previous entered number(int) with next one continuously and I need to write a program that repeatedly reads numbers from the user’s keyboard. The program stops looping when the user types the same number twice in a row.
Thanks in advance for your kind guidance.
Here’s a sample run of the program:
5
13
21
5
4
5
5
Done!
Following was my unsuccessful effort :)
Scanner input = new Scanner(System.in);
System.out.println("Enter Numbers");
int x = 0;
int y = 0;
x = input.nextInt();
y = input.nextInt();
while (x != y) {
x = input.nextInt();
y = input.nextInt();
}
System.out.println("Done!!!!!!!");
input.close();
You can use loop to read number from console and stop if previous nubmer equals to current one. As marker of first number you can use e.g. null value of Integer prv (as alternative, you can use boolean isFirstLine flag for first line or res.isEmpty()).
public static List<Integer> receiveNumbers() {
List<Integer> res = new LinkedList<>();
Integer prv = null;
try (Scanner scan = new Scanner(System.in)) {
while (true) {
int num = scan.nextInt();
if (prv != null && prv == num)
break;
res.add(num);
prv = num;
}
}
return res;
}
import java.util.Scanner;
public class OngoingPractice {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int previous, current;
previous = keyboard.nextInt();
current = keyboard.nextInt();
while (current != previous) {
previous = current;
current = keyboard.nextInt();
}
System.out.println("Done!");
Just use an infinite while loop and break if the new int is equal to previous one. As a suggestion you should show how you tried.
Scanner sc = new Scanner(System.in);
int i;
Integer j = null;
boolean flag = false;
while(true) {
i = sc.nextInt();
if(j==null) {j=i; flag = true;}
if(j==i&&!flag) {
System.out.println("Done");
break;}
j=i;
flag = false;
}
Edited : if first one is -1, it won't work as in the comment. so I modified some.
Remember the last entered data in one variable and check it with the current data. If both matches, break the loop.
Scanner scanner = new Scanner(System.in);
String previousNumber="";
while (scan.hasNextInt()) {
int number = scan.nextInt();
if(!previousNumber.equals("") && number==Integer.parseInt(previousNumber)) {
break;
}else {
System.out.println(number);
}
previousNumber=number+"";
}

Parsing through a file that uses whitespace as a delimiter -java. (I dont understsand it)

Could someone help me understand what I am doing wrong please?
I have to read through a file with 11 integers and doubles on each line, each line needs to become its own object and stored in an arrayList. However, the delimiter is a single space. And I have used this code, but it doesnt seem to work and I am not sure what I am doing wrong.
package p2_0000000;
import java.util.Scanner;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
public class P2_000000 {
public static void main(String[] args) {
// TODO code application logic here
System.out.println("Which file year would you like to analyze:\n"
+ "1) 2007\n"
+ "2) 2011\n"
+ "3) 2013\n"
+ "(Enter number for choice)");
Scanner input = new Scanner(System.in);
int choice = input.nextInt();
ArrayList<dwellingClass> alist = new ArrayList<dwellingClass>();
if (choice == 1) {
try {
File file = new File("2007.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String[] info = line.split(" ");
int age = Integer.parseInt(info[0]);
int region = Integer.parseInt(info[1]);
double lmed = Double.parseDouble(info[2]);
double fmr = Double.parseDouble(info[3]);
double extremelyLowIncome = Double.parseDouble(info[4]);
double veryLowIncome = Double.parseDouble(info[5]);
double lowIncome = Double.parseDouble(info[6]);
int bedrooms = Integer.parseInt(info[7]);
double value = Double.parseDouble(info[8]);
int rooms = Integer.parseInt(info[9]);
double utility = Double.parseDouble(info[10]);
dwellingClass dwelling = new dwellingClass(age, region, lmed, fmr, extremelyLowIncome, veryLowIncome, lowIncome, bedrooms, value, rooms, utility);
alist.add(dwelling);
}
scanner.close();
} catch (Exception a) {
a.printStackTrace();
System.exit(0);
};
for (dwellingClass each : alist) {
System.out.println(each);
}
}
System.out.println(alist.get(0).getAge());
}
}
I get these errors:
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:592)
at java.lang.Integer.parseInt(Integer.java:615)
Thank you everyone for the help!
I also figured out that this could also work for anyone who reads this post later:
public class P2_0000000 {
public static void main(String[] args) {
// TODO code application logic here
ArrayList<dwellingClass> alist = new ArrayList<dwellingClass>();
try {
File file = new File("2007.txt");
Scanner input = new Scanner(file);
while (input.hasNext()) {
int age = input.nextInt();
int region = input.nextInt();
double lmed = input.nextDouble();
double fmr = input.nextDouble();
double extremelyLowIncome = input.nextDouble();
double veryLowIncome = input.nextDouble();
double lowIncome = input.nextDouble();
int bedrooms = input.nextInt();
double value = input.nextDouble();
int rooms = input.nextInt();
double utility = input.nextDouble();
dwellingClass dwelling = new dwellingClass(age, region, lmed, fmr, extremelyLowIncome, veryLowIncome, lowIncome, bedrooms, value, rooms, utility);
alist.add(dwelling);
}
input.close();
} catch (Exception a) {
a.printStackTrace();
System.exit(0);
};
for (dwellingClass each : alist) {
System.out.println(each.getAge() + each.getRegion());
}
System.out.println(alist.get(0).getAge());
}
}
First you can read the file this way:
Scanner in = new Scanner(new FileReader("2007.txt"));
Secondly to parse white spaces you will need to use something like this:
yourString.split("\\s+");
So your this line should become:
String[] info = line.split("\\s+");
Then you can access your String the way you did it.
But make sure that you are passing the right values i.e. the right types to each of the methods otherwise yo will get the error you are getting.
You should do a number validation of the string you read from the file and make sure that it matches the requirements for building your dwellingClass object.
String line = scanner.nextLine();
String[] info = line.split("\\s+");
boolean validInput = true;
//loop through your info array and check each number is valid beforehand
for(int i = 0; i < info.length; i++)
{
if(!info[i].matches("\\d"))
{
validInput = false;
break;
}
}
//now we want to make sure our input was valid or else we don't create the object
if(info.length == 11 && validInput == true)
{
dwellingClass dwelling = new dwellingClass(
Integer.parseInt(info[0]),
Integer.parseInt(info[1]),
Double.parseDouble(info[2]),
Double.parseDouble(info[3]),
Double.parseDouble(info[4]),
Double.parseDouble(info[5]),
Double.parseDouble(info[6]),
Integer.parseInt(info[7]),
Double.parseDouble(info[8]),
Integer.parseInt(info[9]),
Double.parseDouble(info[4]));
alist.add(dwelling);
}
If you put this inside your while loop it will only create objects with lines read from the file that contain only numbers and contains 11 digits, other lines will simply be ignored. This would allow execution of the file even if a line is not formatted correctly.
You are creating a NEW file, not loading your file. To load a file, you need to use a file input stream. your Scanner wont find anything in a new file and thus its all Null
I stand corrected, the syntax is correct and this would load an existing file. As others have mentioned above its a data issue

No Such Element Exception. I'm stuck

Code:
package FisherTCh5Sec4to5;
import java.util.Scanner;
public class FisherTCh5Sec4to5 {
public static int generateRandomInt(int lowerLimit, int upperLimit){
int range = (upperLimit - lowerLimit) + 1;
int randomInt = (int) Math.random() * range + lowerLimit;
return randomInt;
}//end generate random int
public static int collectInteger(String purpose, int minimum, int maximum){
Scanner in = new Scanner(System.in);
int userInt = 0;
boolean done = false;
do {
System.out.printf(purpose);
if (in.hasNextInt()){
userInt = in.nextInt();
if (userInt >= minimum && userInt <= maximum){
done = true;
} else System.out.printf("That number isn't in the desired range.\n");
} else System.out.printf("Sorry...I can't use that input.\n");
//Clear input stream
in.nextLine();
} while (!done);
in.close();
return userInt;
}// end method
public static void main(String[] args) {
// Variables
final int LOWER_LIMIT = 1;
final int UPPER_LIMIT = 10;
boolean done = false;
String playAgain = "";
int count = 0;
int wins = 0;
// Open input stream
Scanner in = new Scanner(System.in);
do {
// Use collectInteger to get a number
int userInput = collectInteger("Let's play a game! Try and guess my number (between 1 and 10): ", LOWER_LIMIT,
UPPER_LIMIT);
// use generateRandomInt to get a number
int randomInt = generateRandomInt(LOWER_LIMIT, UPPER_LIMIT);
// If statement to decide a win or loss
if (userInput == randomInt){
System.out.printf("Congrats you win! My number was %d.\n", randomInt);
wins++;
} else System.out.printf("Sorry...my number was %d.\n", randomInt);
// Ask user to play again
System.out.print("Would you like to continue? (\"c\" to continue \"q\" to quit): ");
playAgain = in.next();
if (playAgain.equals("c")){
done = false;
} else done = true;
count ++;
} while(done = false);
// Print and calculate win percentage
double winPercent = (wins / count) * 100;
System.out.printf("Wow! Your win percentage was %.2f%%.\n", winPercent);
// close input stream
in.close();
}//end main
}//end class
Everything is working beautifully except for the "Would you like to play again" portion. It won't let me read in the user input I think. Any ideas?
Your first call to in.close() inside collectInteger() also closes your System.in input stream. This is not reopened when you instantiate a new Scanner. Don't believe me? Test it with
System.out.println( System.in.available() ); // Inside try/catch
You have a few options...
ONE instance of Scanner inside main() – pass the scanner as an argument to collectInteger(). Inside collectInteger() you will need to replace in.close() with in.reset(). Close the scanner inside main when you no longer need it (or System.in).
Global variable - private static Scanner in = new Scanner( System.in ); – You will not need to pass it as a parameter but creates tighter coupling. Again - close it only when you no longer need System.in
Keep multiple Scanners but only close the one inside main – Not recommended but the stream will close in jvm shutdown.
I would also surround any IO operations with try/catch/finally...
try
{
// open resource
// read/write operation
}
catch( /*specific exception(s)*/ )
{
// handle exception
}
finally
{
// close resource
}
Another issue:
boolean done = false; // Currently redundant
do {
...
// Ask user to play again
System.out.print("Would you like to continue? (\"c\" to continue \"q\" to quit): ");
playAgain = in.next();
if (playAgain.equals("c")){
done = false; // Already initialized to false
} else done = true;
count ++;
} while(done = false);
Could be changed to:
boolean done = false;
do {
...
// Ask user to play again
System.out.print("Would you like to continue? (\"c\" to continue \"q\" to quit): ");
playAgain = in.next();
if (playAgain.equals("q")){ // CHANGE
done = true; // CHANGE
}
count ++;
} while(!done); // CHANGE
The line in.close(); in collectInteger closes the input from System.in. Remove that line and it should work.
Also this line: while(done = false);
Should be changed to:while(done == false); or while(!done);
Reasoning: By using one equal sign, you are setting done to false every time the loop condition is checked. This means the loop never iterates as the condition is always false.

How to make my code accepts an input

I would just like to ask on how can I make my code to just get the input instead of declaring it? Here's my program. I want to input different atomic numbers and not just "37" like what's in my code. Don't mind my comments, it's in my native language. Thanks!
public class ElectConfi {
public static void main(String s[]) {
int atomicNumber = 37;
String electronConfiguration = getElectronConfiguration(atomicNumber);
System.out.println(electronConfiguration);
}
public static String getElectronConfiguration(int atomicNumber) {
int[] config = new int[20]; //dito nag store ng number of elec. in each of the 20
orbitals.
String[] orbitals = {"1s^", "2s^", "2p^", "3s^", "3p^", "4s^", "3d^", "4p^", "5s^",
"4d^", "5p^", "6s^", "4f^", "5d^", "6p^", "7s^", "5f^", "6d^", "7p^", "8s^"};
//Names of the orbitals
String result="";
for(int i=0;i<20;i++) //dito ung i represents the orbital and tapos ung j
represents ng electrons
{
for(int j=0;(getMax(i)>j)&&(atomicNumber>0);j++,atomicNumber--) //if atomic
number > 0 and ung orbital ay kaya pa magsupport ng more electrons, add
electron to orbital ie increment configuration by 1
{
config[i]+=1;
}
if(config[i]!=0) //d2 nagche-check to prevent it printing empty
orbitals
result+=orbitals[i]+config[i]+" "; //orbital name and configuration
correspond to each other
}
return result;
}
public static int getMax(int x) //returns the number of max. supported electrons by each
orbital. for eg. x=0 ie 1s supports 2 electrons
{
if(x==0||x==1||x==3||x==5||x==8||x==11||x==15||x==19)
return 2;
else if(x==2||x==4||x==7||x==10||x==14||x==18)
return 6;
else if(x==6||x==9||x==13||x==17)
return 10;
else
return 14;
}
}
You can use either a Scanner or BufferedReader and get the user input
Using Scanner
Scanner scanner = new Scanner(System.in);
System.out.println("Please input atomic number");
int atomicNumber = scanner.nextInt();
Using BufferedReader
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int atomicNumber = Integer.parseInt(reader.readLine());
public static String getElectronConfiguration(int atomicNumber) {}
This method accepting any int value and will return String result. so you only need to provide different number as input. There is no change required in this method.
How to provide different inputs?
You can use Scanner to do that.
Scanner scanner = new Scanner(System.in);
System.out.println("Please input atomic number");
int atomicNumber = scanner.nextInt();
Now call your method
String electronConfiguration = getElectronConfiguration(atomicNumber);
What are the other ways?
You can define set of values for atomicNumber in your code and you can run those in a loop
You can get input from command line arguments by doing below :
Scanner scanner = new Scanner(System.in);
String inputLine = scanner.nextLine(); //get entire line
//or
int inputInt= scanner.nextInt();//get an integer
Check java.util.Scaner api for more info - http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
Hope this helps!
You can get the user input from a command line argument:
public static void main(String s[]) {
if (s.length == 0) {
// Print usage instructions
} else {
int atomicNumber = Integer.parseInt(s[0]);
// rest of program
}
}

Let user input integers until "X" is pressed Java

Basically what I have to do is read user input in (CUI) until the user presses x. Then display the min,max and average of the numbers the user has entered. I keep getting a InputMismatchException when I press x. I have tried a lot of different ways and that is why I may have some unnecessary code in there.
import java.io.*;
import java.util.Scanner;
import java.lang.Number;
public class taskTwo{
public static void main(String [] args) throws IOException {
int min = 0;
int max = 0;
boolean isX =false;
Scanner input = new Scanner (System.in);
BufferedReader input2 = new BufferedReader (new InputStreamReader (System.in));
String s = "x";
s = input2.readLine();
while(isX == false){
if(s.equals ("x") || s.equals ("X")){
isX = true;
}
int val = input.nextInt();
if (val == 0) {
break;
}
if (val < min) {
min = val;
}
if (val > max) {
max = val;
}
}
if(isX == true){
System.out.println("Min: " + min);
System.out.println("Max: " + max);
}
}
}
in the while loop you are using nextInt(), obviously it will expect an integer as input. So when you are giving input x which is an string then it will fail.
So in the loop take string as input and if it is not X and is a number then convert it to int values and calculate
s = input2.readLine(); is called outside while loop means only for first line it will check for X and loop can never be ended if fist line is not X or you entered 0.
1.) You don't need two objects reading input. Just input is sufficient.
2.) You can use
input.hasNextInt();
and
input.hasNext();
to check if the input is an int or a string. Something like:
while(true){
if(input.hasNextInt()){
//do something with the integer
}else if(input.hasNext()){
if(input.next().toLowerCase() == "x"){
break;
}
}
}

Categories