How to deal with NoSuchElementException in java? - java

I have a java program that reads from a cvs file that looks like this:
1111,John,23
2222,Mary,32
...
I want to store each field in an array. Whenever I run the following program I get the following message:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
How can I deal with that exception? I guess it is because scanner reads beyond its limit, however, doesn't the while block ensure that it will read within its limits?
Any help is appreciated
import java.util.*;
import java.io.*;
public class program
{
public static void main(String[] args) throws FileNotFoundException, IOException
{
BufferedReader br = new BufferedReader(new FileReader("info.csv"));
int[] ids = new int[20];
String[] names = new String[20];
int[] age = new int[20];
String line;
int i = 0;
while( (line = br.readLine()) != null)
{
Scanner s = new Scanner(line).useDelimiter(",");
ids[i] = s.nextInt();
names[i] = s.next();
sales[i] = s.nextInt();
s.close();
i++;
}
for(int j = 0; j < 20; j++)
{
System.out.println("Id: "+ids[i]+" Name: "+names[i]+" Age: "+ age[i]);
}
}
}

Reading CSV files is actually quite complicated. Handling quotes and newlines is quite difficult. There are also encoding issues to consider (which you haven't; you should basically never use this constructor FileReader, as it uses 'platform default encoding'). Don't reinvent this wheel; use something like super-csv.
The while block ensures you read each line once and don't read beyond the end of the file. Per line you forcibly go: an int, a string, and an int, period. That's where the crash occurs. Mostly likely there's a trailing newline at the end of the file or some such. A trivial example would be to check if line.trim() is empty, and if so, to just move on (continue;) and not attempt to read the line.
But, really, don't handroll this, get a CSV parser.
NB: If you must reinvent this wheel, there are far nicer and easier ways to get all lines from a file. For example, Files.newBufferedReader(Paths.get("/path/to/whatsit")) or even Files.lines(Paths.get("/path/to/whatsit")), conveniently those methods also default to UTF-8, i.e. a consistent choice instead of 'flip a coin and pray'.

Try to use split(,)
String[] split = line.split(",");
if (split.length >= 0) {
String input = split[0];
if (input.matches("[0-9]+"))
ids[i] = Integer.parseInt(input);
}
if (split.length >= 1) {
names[i] = split[1];
}
if (split.length >= 2) {
String input = split[2];
if (input.matches("[0-9]+"))
ids[i] = Integer.parseInt(input);
}

Related

It is throwing exception java.lang.NumberFormatException: Cannot parse null string?Why?

this is in main method I just Want to sum the numbers available in the text file located in E:\Java_Examples\data.txt.
int sum = 0;
try {
FileReader f1 = new FileReader("E:\\Java_Examples\\data.txt");
BufferedReader s1=new BufferedReader(f1);
String line="";
while(s1.readLine()!=null)
{
line=s1.readLine();
sum+=Integer.parseInt(line);
}
s1.close();
} catch(IOException e)
{
System.out.println("File not found");
}
Can anyone help with this?
It is throwing exception java.lang.NumberFormatException: Cannot parse
null string?Why?
Because you are calling readLine after the stream is empty.
Instead of this...
while(s1.readLine()!=null)
{
line=s1.readLine();
sum+=Integer.parseInt(line);
}
You could do something like this...
while((line = s1.readLine())!=null)
{
sum+=Integer.parseInt(line);
}
This sort of bug, and the large amount of code required for the simple task, happens when you write low-level code instead of using simpler approaches offered by the JDK.
Use Scanner:
int sum = 0;
Scanner scanner = new Scanner(new FileInputStream("E:/Java_Examples/data.txt"));
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
sum += Integer.parseInt(line);
}
Or use Files for a one liner:
int sum = Files.lines(Paths.get("E:/Java_Examples/data.txt"))
.mapToInt(Integer::parseInt)
.sum();

Need help fixing NumberFormatException error [duplicate]

This question already has answers here:
Scanner is skipping nextLine() after using next() or nextFoo()?
(24 answers)
Closed 1 year ago.
I'm trying to read in a text file which looks similar to this:
0000000000
0000100000
0001001000
0000100000
0000000000
Here is my code:
public static int[][] readBoard(String fileName) throws FileNotFoundException {
File life = new File(fileName);
Scanner s = new Scanner(life);
int row = s.nextInt();
int columns = s.nextInt();
int [][] size = new int [row][columns];
for (int i=0; i <= row; i++) {
String [] state = new String [columns];
String line = s.nextLine();
state = line.split("");
for (int j=0; i <= columns; i++) {
size[i][j] = Integer.parseInt(state[j]);
}
}
return size;
}
It keeps giving me this error. I think it's the Integer.parseInt(state[j]) that is giving me trouble, but I don't know why.
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at Project5.readBoard(Project5.java:33)
at Project5.main(Project5.java:9)
I've executed your code with the example input, and you have logical issues in the code. With the exmaple input the code doesn't even reach the parseInt() line where the asked NumberFormatException could be thwrown. I assume you have tried your code in a different input. The Exception message is staithforward, you tried to parse an empty string to number. It's a typical NumberFormatException. The parseInt() function can throw Exception, so your code must be prepared for it.
The other problem is a basic logical issue in your algorithm. Your row and column variables will be populated with the first to integer token from the text. Based on the exampe input the first integer token will be the first row 0000000000 which integer value is 0, and the second token is 0000100000 which will parsed as 100000. So you are trying to initialize an array with these dimensions which is imposible.
To calculate the row count, you have to read the file line by line. And to get the column counts you have the check the length of the lines. (It can open a new question, how do you want to handle the not properly formatted input file, because in the file the line length can be various.)
That means you can only be sure with the dimensions of the board if you have already iterated though the file content. To prevent the multiple iteration you should use dinamic collection instead of a standard array, like ArrayList.
That means while you are read the file line by line, you can process the the characters one after another in a line. In this step you should be concidered about the invalid characters and the potential empty characters in the end of the file. And during this iteration the final collection can be built.
This example shows a potention solution:
private static int processCharacter(char c) {
try {
return Integer.parseInt((Character.toString(c)));
} catch (NumberFormatException e) {
return 0;
}
}
public static List<List<Integer>> readBoard(String fileName) throws FileNotFoundException {
List<List<Integer>> board = new ArrayList<>();
File file = new File(fileName);
FileReader fr = new FileReader(file);
try (BufferedReader br = new BufferedReader(fr)) {
String line;
while ((line = br.readLine()) != null) {
line = line.trim(); // removes empty character from the line
List<Integer> lineList = new ArrayList<>();
if(line.length() > 0) {
for (int i = 0; i < line.length(); i++) {
lineList.add(Main.processCharacter(line.charAt(i)));
}
board.add(lineList);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return board;
}

How can I read lines from a inputted file and then store the most recently read lines in an array?

I am trying to create a program that takes an inputted text file and reads the lines one by one. It then needs to store the most recently read lines (the number of lines depends on the parameter lines) in an array and then I need to print the lines using PrintWriter.
I started the first part but I'm not sure if I have the right idea. If anyone can help me on the second part as well that would be very appreciated!
public void RecentLines(Reader in, Writer out, int lines) throws IOException {
BufferedReader r3ader = new BufferedReader(in);
String str;
while((str = r3ader.readLine()) != null){
String[] arr = str.split(" ");
for( int i =0; i < lines; i++){
arr[i] = r3ader.readLine();
}
}
EDIT
the full question is this:
Create a program which reads lines from IN, one line at the time until the end. Your method must maintain an internal buffer that stores the most recently read lines (this might be best done using an array). Once the method reaches the end of the file, it should print the lines stored in the internal buffer into out, probably best done by creating a PrintWriter to decorate this Writer. (Except for your debugging purposes during the development stage, this method should not print anything to System.out.)
Try this one:
public void RecentLines(Reader in, Writer out, int lines) throws IOException {
BufferedReader r3ader = new BufferedReader(in);
String str;
int i=0;
String[] lineArray = new String[lines];
while((str = r3ader.readLine()) != null){
lines[i%lines] = str;
i++;
if(!r3ader.hasNextLine()){
break;
}
}
sounds like a task for data structures. Queue seems to be the best fit for a given task.
public void RecentLines(Reader in, Writer out, int lines) throws IOException {
BufferedReader r3ader = new BufferedReader(in);
BufferedWriter wout = new BufferedWriter(out);
String str;
Queue<String> content = new LinkedList<String>();
int i = 0;
while ((str = r3ader.readLine()) != null) {
if (i >= lines) {
content.remove();
}
content.add(str);
i++;
}
wout.write(String.valueOf(content));
}

Java elementary code snippet

I am a newbie to Java and would be very grateful if someone could look into this code snippet and give me a hand.
#SuppressWarnings("unused")
public static void main(String[] args) throws IOException {
File fin = new File("wordList");
FileInputStream fis = new FileInputStream(fin);
BufferedReader br = new BufferedReader(new nputStreamReader(fis));
List<String> wordList = new ArrayList<>();
List<Character> guessedCharacters = new ArrayList<>();
char guessedCharacter;
String line = "";
while ((line = br.readLine()) != null) {
wordList.add(line);
}
br.close();
System.out.println("Welcome to hanged man.");
System.out.println();
for (int i = 0; i < wordList.size(); i++) {
System.out.print("Guess a letter: ");
guessedCharacter = (char) System.in.read();
System.out.println('\n');
}
When I run the code snippet above I get the following output:
Welcome to hanged man.
Guess a letter: d
Guess a letter:
Guess a letter:
My intention is to have the prompt "Guess a letter" appear only once after I enter the first letter.
If I replace "wordList.size()" in the for-loop with any integer larger than three I get the same result.
I hope to hear from someone. Thank you in advance. Marcos
What you are looking for is either using the Scanner class (probably not, as your exercise looks trivial and you probably just want the easiest way to read keyboard inputs without any GUI) or, most probably, this :
String answer = System.console().readLine("Guess a letter : ");
Don't use System.read() to read keystrokes (or unless you want to complicate things "just for the fun" :)
With System.read.in() you read 'd' and '\n' values. Try to use Scanner class (see here)

JAVA - import CSV to ArrayList

I'm trying import CSV file to Arraylist using StringTokenizer:
public class Test
{
public static void main(String [] args)
{
List<ImportedXls> datalist = new ArrayList<ImportedXls>();
try
{
FileReader fr = new FileReader("c:\\temp.csv");
BufferedReader br = new BufferedReader(fr);
String stringRead = br.readLine();
while( stringRead != null )
{
StringTokenizer st = new StringTokenizer(stringRead, ",");
String docNumber = st.nextToken( );
String note = st.nextToken( ); /** PROBLEM */
String index = st.nextToken( ); /** PROBLEM */
ImportedXls temp = new ImportedXls(docNumber, note, index);
datalist.add(temp);
// read the next line
stringRead = br.readLine();
}
br.close( );
}
catch(IOException ioe){...}
for (ImportedXls item : datalist) {
System.out.println(item.getDocNumber());
}
}
}
I don't understand how the nextToken works, because if I keep the initialize three variables (docNumber, note and index) as nextToken(), it fails on:
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(Unknown Source)
at _test.Test.main(Test.java:32)
If I keep docNumber only, it works. Could you help me?
It seems that some of the rows of your input file have less then 3 comma separated fields.You should always check if tokenizer has more tokens (StringTokenizer.hasMoreTokens), unless you are are 100% sure your input is correct.
CORRECT parsing of CSV files is not so trivial task. Why not to use a library that can do it very well - http://opencsv.sourceforge.net/ ?
Seems like your code is getting to a line that the Tokenizer is only breaking up into 1 part instead of 3. Is it possible to have lines with missing data? If so, you need to handle this.
Most probably your input file doesn't contain another element delimited by , in at least one line. Please show us your input - if possible the line that fails.
However, you don't need to use StringTokenizer. Using String#split() might be easier:
...
while( stringRead != null )
{
String[] elements = stringRead.split(",");
if(elements.length < 3) {
throw new RuntimeException("line too short"); //handle missing entries
}
String docNumber = elements[0];
String note = elements[1];
String index = elements[2];
ImportedXls temp = new ImportedXls(docNumber, note, index);
datalist.add(temp);
// read the next line
stringRead = br.readLine();
}
...
You should be able to check your tokens using the hasMoreTokens() method. If this returns false, then it's possible that the line you've read does not contain anything (i.e., an empty string).
It would be better though to use the String.split() method--if I'm not mistaken, there were plans to deprecate the StringTokenizer class.

Categories