How to avoid NumberFormatException while using BufferedReader? - java

I used BufferedReader to read data from the user, but it gives NumberFormat Exception prvovided I give the input in a certain way. Suppose in C, I write the code like this:
scanf("%d %d", &x, &y);
and i try to give the input to the console like this : 23 45, it assigns values like this:
x = 23, y = 45
How can I do something like this in java. I tried like this :
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
String line1 = br1.readLine();
String line2 = br2.readLine();
int x = Integer.parseInt(line1);
int y = Integer.parseInt(line2);
But this gives:
Exception in thread "main" java.lang.NumberFormatException: For input
string: "23 45" at
java.lang.NumberFormatException.forInputString(Unknown Source) at
java.lang.Integer.parseInt(Unknown Source) at
java.lang.Integer.parseInt(Unknown Source) at AB.main(AB.java:23)

readLine() reads until there is a newline, usually meaning that the user pressed enter.
If you input 12 34, this is one line, a line that isn't formatted like an integer.
You can either read a single char at a time by using read() instead, split the line manually and parse the results, or preferably use the Scanner class instead. It has a more user-IO oriented api, exposing methods such as nextInt() or next() (returning the next "token" instead of the next char) and so on.
Scanner in = new Scanner(System.in);
int x = in.nextInt();
int y = in.nextInt();

If you really want to pass both parameters on the same line, split the line on the white spaces, then use each token separately :
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
String line1 = br1.readLine();
String[] tokens = line1.split("\\s+")
int x = Integer.parseInt(tokens[0]);
int y = Integer.parseInt(tokens[1]);

Now here we are - many, many answers just explaining how to read correct input. But you'll get NumberFormatExceptions any other odd way. Like if your input would be...
98765432109876543210 9876543210987654321
This would in turn throw NumberFormatException as these are too large to fit into int.
So while splitting at " " and addressing tokens manually is good advice, you'd also run into ArrayIndexOutOfBounds if for instance only one number was given.
My recommendation would be to check if the input looks valid before you do any further parsing:
Scanner s = new Scanner(System.in);
String line = s.nextLine();
Pattern p = Pattern.compile("(\\d{1,10})\\s+(\\d{1,10})");
Matcher m = p.matcher(line);
if(m.matches()) {
long x1 = Long.parseLong(m.group(1));
long y1 = Long.parseLong(m.group(2));
if(x1 <= Integer.MAX_VALUE&& y1 <= Integer.MAX_VALUE) {
int x = (int)x1;
int y = (int)y1;
System.out.printf("Your input: %d / %d", x, y);
} else {
System.err.println("Numbers too big");
}
} else {
System.err.println("Input does not match criteria");
}

One InputStreamReader is enough:
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
String line1 = br1.readLine();
String[] args = line1.split(" ");
if (args.length != 2) {
throw new IllegalArgumentException("The input is wrong");
}
int x = getIntFromInput(args[0]);
int y = getIntFromInput(args[1]);
and as Jan pointed out you will need a convertion method:
public static int getIntFromInput(String inputString) {
//sanity checks
if (inputString == null || inputString.trim().length() == 0) {
throw new IllegalArgumentException("empty or null string passed");
}
try {
return new BigInteger(inputString, 10).intValueExact();
} catch (Exception ignored) {
throw new IllegalArgumentException(String.format("input string is not a valid integer number: '%s'", inputString));
}
}

This will solve your purpose
int x, y;
String[] input;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
input = str.split(" ");
x = Integer.parseInt(input[0]);
y = Integer.parseInt(input[1]);

You have to do something like that:
String in = *getline*;
String[] tab = in.split(' ');
List<int> nums = new ArrayList<int>();
for(String a : tab){
nums.add(Integer.parseInt(a)); // or push() not remember...
}
// Your nums have your integers now

You can read data from file and split string based upon 1 or more space and can handle multiple inputs separated by space.
Scanner s = new Scanner(System.in);
String line = s.nextLine();
//String line = "98765432109876543210 9876543210987654321 ";
String[] splited = line.split("\\s+");
Then compare each string to check whether it is valid number.
Then create a new BigDecimal from that number. A BigDecimal on 64bit jvm with with memory permitting can hold upto 646456993 digits.
for (int i=0;i<splited.length;i++) {
if(splited[i].matches("[0-9]*")){
BigDecimal num = new BigDecimal(splited[i]);
System.out.println("num "+(i+1)+"="+num);
}
}
Results
line ="98765432109876543210 9876543210987654321 "
num 1=98765432109876543210
num 2=9876543210987654321
line ="1212312312312312312312313 123432432432432423432423432"
num 1=1212312312312312312312313
num 2=123432432432432423432423432

Related

Comma Separated User input in java

Below are the inputs:
Event Name, Date, No. of attendees
Catering party, 01/01/2018, 100
Wedding,24/01/2018,500
Bike Stunts show, 06/01/2018, 300
Below is the code:
public static void main(String[] args) throws ParseException {
//SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
List<Event> events = new ArrayList<>();
for (int i = 0; i < n; i++) {
sc.next();
//String line=sc.nextLine();
String parts[] = sc.nextLine().split(", ");
//StringTokenizer st = new StringTokenizer(line,", ");
//int j=0;
//while(st.hasMoreTokens()) {
//System.out.println(st.nextToken());
//parts[j]=st.nextToken();
//j++;
//}
//System.out.println(j);
//String[] inputs = sc.nextLine().split(", ");`
for (String data : parts) {
System.out.println(data);
}
String name = parts[0].trim();
String date = parts[1].trim();
String attendee = parts[2].trim();
int count = Integer.parseInt(attendee);
events.add(new Event(name, date, count));
}
}
Below is the Error:
3Number of inputs
Catering party, 01/01/2018, 100
party
01/01/2018
100
Wedding, 24/01/2018, 500
24/01/2018
500
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at Main.main(Main.java:74)
I have tried both String Tokenizer and split method but as you can see in the error that I am not able to take the input in correct format. Please help me to know what is wrong in my code.
Hello Everyone! After getting stuck with sc.next() and sc.nextLine() I have used BufferedReader to take the input. And it is working below is the code:
for (int i = 0; i < n; i++) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line=reader.readLine();
String parts[] = line.trim().split(",");
for (String data : parts) {
System.out.println(data);
}
name = parts[0].trim();
date = parts[1].trim();
attendee = parts[2].trim();
count = Integer.parseInt(attendee);
events.add(new Event(name, date, count));
}
You may have noticed that, from your debug logs, you're not getting the correct output even before the IndexOutOfBoundsException. This is due to the sc.next(); that you added at the beginning of the for loop. This is also the reason behind the exception in the second iteration.
What is actually happening
The compiler is reading the first non-space seperated integer characters through sc.nextInt();
Then, in the for loop, you are reading the next non-space seperated string through sc.next();. In your case, that's the word "Catering".
After that, the compiler is reading the rest of the line as "party, 01/01/2018, 100" and operating on it. This is why you are only getting the word "party" in the sysout rather than "Catering party".
The same happens for the next line of input, except this time the entirety of "Wedding," is considered a single sc.next() so you end up with "24/01/2018, 500" and an IndexOutOfBoundsException.
The only reason the first line worked is because it had two words in the first argument so it didn't affect the split array size.
Solution
I would recommend you try to fix it yourself before reading this next part. Consider using the debugger! It's a very helpful tool.
after reading the initial number input sc.nextInt() you should add sc.nextLine(); so that the compiler understands that the previous line is finished and the next read should be on a new line.
You should remove sc.next(); as this accomplishes nothing. (I'm guessing you added this to try and solve the issue where the compiler wasn't reading the next line as mentioned previously).
Finally, I would recommend you split on , rather than , since you're trimming the strings anyway.
#alankar's solution
I have used BufferedReader and now I am able to take input.
for (int i = 0; i < n; i++) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line=reader.readLine();
String parts[] = line.trim().split(",");
for (String data : parts) {
System.out.println(data);
}
name = parts[0].trim();
date = parts[1].trim();
attendee = parts[2].trim();
count = Integer.parseInt(attendee);
events.add(new Event(name, date, count));
}
try to remove white spaces before splitting your input, to make sure there is no white spaces that can affect your separator, also you have to check if the user has entered three fields separated by comma. Here's an example:
public static void main(String[] args) throws ParseException {
//SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
List<Event> events = new ArrayList<>();
for (int i = 0; i < n; i++) {
sc.next();
//String line=sc.nextLine();
String parts[] = sc.nextLine().trim().split(",");
if (parts.length != 3) {
throw new IllegalArgumentException("Error: Input must have 3 parts separated by comma");
}
String name = parts[0];
String date = parts[1];
String attendee = parts[2];
int count = Integer.parseInt(attendee);
events.add(new Event(name, date, count));
}
}

If condition is met -> scan input into one variable. If not -> scan input into another variable

Scanner input = new Scanner(System.in)
System.out.print("Enter either a string or a number");
String str = input.nextLine();
int x = input.nextInt();
The program here expects 2 values, a string and an integer. YET there is only one.
I want str to register the value if it is a string, BUT if it is an integer, I want the value to be registered by x
In other words, I only want one of the variables to be active
if the value of entered is an integer, then you can simply use regex where
if(str.matches("\\d+") || str.matches("-\\d+"))
checks if the entered number is a number of 1 or more digits or the entered number is a negative number with one or more digits
and if that is the case, then you can x = Integer.parseInt(str); to convert that entered string into integer and make str = ""; otherwise , the entered string is stored in str and never parsed to int
and this is the edited code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter either a string or a number\n");
String str = input.nextLine();
int x = 0;
if(str.matches("\\d+") || str.matches("-\\d+"))
{
x = Integer.parseInt(str);
str = "";
}
else
{
// nothing to do
}
System.out.println("x = " + x);
System.out.println("str = " + str);
}
}
and this is some example output:
Enter either a string or a number
10
x = 10
str =
Enter either a string or a number
test
x = 0
str = test
Enter either a string or a number
-30
x = -30
str =
Enter either a string or a number
test10
x = 0
str = test10
The answer provided by abdo and the comment by Jesse are both valid and very good answers.
However it is also possible to achieve your goal with the Scanner methods. In this case hasNextInt() is your friend.
f
But note, that nextLine() will consume the line break, while nextInt() will not. IMHO it will be more clear to code both options alike and use next() instead.
The most simple approach:
if (input.hasNextInt()) {
x = input.nextInt();
}
else {
str = input.next();
}
input.nextLine(); // consume the line break, too
Here still one issue remains: By default Scanner uses whitespace as delimiter, not line breaks. With the input "4 2\n" nextInt() will return 4 and nextLine() will discard the rest. However the user's intention (number versus string) is not obvious in this case either, therefor I'd tend to create the string "4 2" instead. This can easily be achieved by using line breaks as delimiter instead:
Scanner input = new Scanner(System.in).useDelimiter(System.lineSeparator());
A full demo example:
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
Scanner input = new Scanner(System.in).useDelimiter(System.lineSeparator());
System.out.println("Enter either a string or a number");
String str = null;
while (!"end".equals(str)) {
int x = 0;
str = null;
if (input.hasNextInt()) {
x = input.nextInt();
}
else {
str = input.next();
}
input.nextLine();
if (str != null) {
System.out.printf("we have a string! str=%s%n", str);
}
else {
System.out.printf("we have a number! x=%d%n", x);
}
}
System.out.println("goodbye!");
}
}

String Tokenizer giving exception while taking space saperated values using BufferedReader

I tried to start using BufferedReader instead of Scanner. While coding for a question on codechef (SMRSTR), I tried taking space separated inputs by using StringTokenizer but it is raising exception i.e NumberFormatException. I found some question on StackOverflow regarding it but I think my problem is different, so I posted one.
Input: 1
2 3
2 3
5 100 8
I am getting:
Exception in thread "main" java.lang.NumberFormatException: For
input string: "2 3"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at A.main(A.java:11)
I am getting first input t correctly from br.readLine();
But next inputs n,q are giving the mentioned exception. I think the problem is in the nextToken from StringTokenizer, but still not getting it clearly.
Here is the code:
import java.io.*;
import java.util.*;
class A{
public static void main(String arg[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer s = new StringTokenizer(br.readLine());
int t= Integer.parseInt(br.readLine());
while(t-->0)
{
int n,q,i;
n=Integer.parseInt(s.nextToken());
q=Integer.parseInt(s.nextToken());
int D[]= new int[n];
int Q[]=new int[q];
long x=1;
for(i=0;i<n;i++)
{
D[i]=Integer.parseInt(s.nextToken());
x=x*D[i];
}
for(i=0;i<q;i++)
{
Q[i]=Integer.parseInt(s.nextToken());
if(x>1000000000)
Q[i]=0;
else
Q[i]=(int)(Q[i]/x);
}
for(i=0;i<q;i++)
System.out.print(Q[i]+" ");
System.out.println("");
}
}
}
Assuming your first line is a single number and your second line a string of space separated numbers (if not, edit your question with your actual input)
I think you want to read t this way:
int t = Integer.parseInt(s.nextToken());
Then read your next line into your tokenizer
s = new StringTokenizer(br.readLine());
The code before the while loop should be:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer s = new StringTokenizer(br.readLine());
int t = Integer.parseInt(s.nextToken());
s = new StringTokenizer(br.readLine());
EDIT
You need to read each line in the tokenizer before using the next Int method. This should work.
Input:
1
2 3
2 3
5 100 8
Output:
0 16 1
Working code:
public static void main(String arg[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// read first line in tokenizer
StringTokenizer s = new StringTokenizer(br.readLine());
//parse t
int t = Integer.parseInt(s.nextToken());
// read second line in tokenizer
s = new StringTokenizer(br.readLine());
while(t-->0) {
int n,q;
// parse n and q (2, 3)
n=Integer.parseInt(s.nextToken());
q=Integer.parseInt(s.nextToken());
int D[]= new int[n];
int Q[]=new int[q];
long x=1;
// read third line in tokenizer
s = new StringTokenizer(br.readLine());
for(int i=0;i<n;i++) {
D[i]=Integer.parseInt(s.nextToken());
x=x*D[i];
}
// read fourth line in tokenizer
s = new StringTokenizer(br.readLine());
for(int i=0;i<q;i++) {
Q[i]=Integer.parseInt(s.nextToken());
if(x>1000000000)
Q[i]=0;
else
Q[i]=(int)(Q[i]/x);
}
for(int i=0;i<q;i++)
System.out.print(Q[i]+" ");
System.out.println("");
}
}

why java BufferedReader miss output

I got error from my code,
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
System.out.print("a = ");
int a=in.read();
System.out.print("b = ");
int b=in.read();
System.out.print(" = "+a);
System.out.print("b = "+b);
i try to input 1,
and i dont understand why the result like this?
a = 1
b = = 49b = 13
Where is the second input going?
You can try something like this:
a = in.readLine();
System.out.print("b = ");
String b=in.readLine();
int aInt = Integer.valueOf(a);
int bInt = Integer.valueOf(a);
System.out.print("a = "+aInt);
System.out.print("b = "+bInt);
read() reads character by character, so newline will be counted as new character. To read more about it you can read here.

Java returning entered text

My first post here on stackoverflow.
The task is:
Write a method that shall return a String, the method has no parameters. The method is going to read some word from the keyboard. The inputs ends with the word "END" the method should return this whole text as a long row:
"HI" "HELLO" "HOW" "END"
Make is so that the method return the string
HIHELLOHOW
MY CODE IS:
import java.util.*;
public class Upg13_IS_IT_tenta {
String x, y, c, v;
public String text(){
System.out.println("Enter your first letter");
Scanner sc = new Scanner(System.in); //Can you even make this outside main?
x = sc.next();
y = sc.next();
c = sc.next();
v = sc.next(); // Here I assign every word with a variable which i later will return. (at the bottom //i write return x + y + c;). This is so that i get the string "HIHELLOWHOW"
sc.next();
sc.next();
sc.next();
sc.next(); // Here I want to return all the input text as a long row
return x + y + c;
}
}
I know that my code has a lot of errors in it, I am new to Java so I would like so help and explaining of what I've done wrong. THANKS!
you can do something like this:
public String text(){
InputStreamReader iReader = new InputStreamReader(System.in);
BufferedReader bReader = new BufferedReader(iReader);
String line = "";
String outputString = "";
while ((line = bReader.readLine()) != null) {
outputString += line;
}
return outputString;
}
Probably you want something like
public String text() {
String input;
String output = "";
Scanner sc = new Scanner(System.in);
input = sc.next();
while (! input.equals("END")) {
output = output + input;
input = sc.next();
}
return output;
}
What you have done now is build a program that can only handle one specific input.
You might want to aim for something more reusable:
public String text(){
System.out.println("Talk to me:");
Scanner sc = new Scanner(System.in);
StringBuilder text = new StringBuilder();
while(!text.toString().endsWith("END"))
{
text.append(sc.next());
}
return text.toString().substring(0, text.toString().length()-3);
}
This builds a single String out of your input, stops when the String ends with "END" and returns the String without the last 3 letters ("END").

Categories