NoSuchElementException when reading CSV file

In summary, the conversation is about an error the user is encountering while trying to implement a try..catch with a while loop in a Java program. The error seems to be caused by an incorrect use of the input.hasNext() and input.next() methods. The conversation also includes a suggestion to use a FileInputStream instead of the current method, and a discussion about sorting an array list with student objects by both ID and name.
  • #1
ProPatto16
326
0
Hello,
Am writing java, using netbeans,
For what should be a simple try.. catch with a while loop, I am getting the error.
i have an excel file with the strings i want to display. the file is all fine, checked to make sure no empty cells etc etc.
When i get to the second last element, the error occurs. there's some 35 elements in the file so the loop is working, its just ending prematurely. i know this is usually because the method call occurs more than necessary i.e. in the loop twice moves it forward too much etc, but in my piece of code I am struggling to find where this is happening.
the following code is the try..catch method that does all the method calling.

Code:
public void readCSVFile()
    {
        StudentList list = new StudentList();
        
        System.out.printf( "%-15s%-15s%-15s%15s\n", "StudentID", "Student Name",
                "Phone", "Email" );
        
        try
        {
            while ( input.hasNext() )
            {
                list.setId( input.next() );
                list.setName( input.next() );
                list.setPhone( input.next() );
                list.setEmail( input.next() );
                
                System.out.printf( "%-15s%-15s%-15s%15s\n",
                        list.getId(), list.getName(), 
                        list.getPhone(), list.getEmail() );
            } // end while
        } // end try
        catch ( NoSuchElementException elementException )
        {
            System.err.println( "File improperly formed." );
            input.close();
            System.exit( 1 );
        } // end catch

just not sure why the iteration is ahead of where it should be. it iterates through 7 cycles then the error is thrown right in between the last call for getName and then the last phone and email arent displayed. its rather strange actually, the 'name' cells in the excel doc are first and last names in each cell, and it only shows the first name of the last person, then throws the error for the rest.

any help would be great :)
 
Physics news on Phys.org
  • #2
Your try block is not as simple as you think. The while loop executes if hasNext() returns true, so the first call to next() inside the loop returns a token. After that, you call next() three more times, but you are not guaranteed that the file will actually contain a token for you to read. My guess is that one of these calls to next() is failing because you have run out of tokens to read. When that happens, next() throws NoSuchElementException.

If that's what is happening, the fix is to call hasNext() each time before you call next(), instead of calling hasNext() once, and then calling next() four times.
 
  • #3
ive tried that, same result. as far as i can work out it seems to be that one particular cell in the file but its identical to the 6 rows above it which are already passed and printed. totally stumped.
 
  • #4
Nevermind guys,
just changed my program to use a fileInputStream :)
 
  • #5
ProPatto16 said:
Nevermind guys,
just changed my program to use a fileInputStream :)

It is still a good idea to make some effort to understand why you were getting the unexpected exception.. I can think of 2 possible reasons:

(1) You tried applying Mark44's advice, but incorrectly did so (what was the exact code block that you had when you added the additional input.hasNext() calls?)

(2) Either input.hasNext() or input.next() is not working the way you think it is
 
  • #6
For implementing marks suggestion, inside the while loop i called the hasNext method as an argument in nested if statements which has the next() call inside the if statements. so then if hasNext returns true, the next() method is called. the use of next() and hasNext() is straight out of an example so I am not sure how i can be using it incorrectly. granted i may not know every exact detail of what is happening, since I am still very much in the learning stages.
 
  • #7
Rather than describing in words the code you tried, show it to us.
 
  • #8
I didn't keep it, all I did was used if (input.hasNext()) before each of the 4 calls to next()
I got it working now though (:
I read all the data into an array list and now I need to sort it. I know collection.sort and I've looked at a lot of other methods but this is tricky. I have the array list with student objects. Each object has the 4 attributes, Id, name, phone, email. Now using collections.sort sorts it in order of id. But I also need to be able to sort it by name, hence the second string in the object. How do you sort the objects in the array list by the second string.

So if I have these 3 entries of a "student" object in an arraylist
14 Jason Luck
17 Sue Brady
10 Adam Prat

Collections.sort will sort then by number, but how do I sort it alphabetically?

Thanks
 
  • #9
Collections.sort will sort a list into ascending order, according to the natural ordering of its elements. How are you sorting your students by ID?
 
  • #10
The student objects are entered into the arraylist in order of ID so if I enter them, then jumble them up, then I just use collection.sort it gets sorted back to in order of ID, hopefully. Havnt quite got there yet. So all the data is entered by order of ID. So I just need a way to sort it in order of name. Then I'll work out how to go back to sorted by number. But since the ID is first thing in the string sorting that is easy. Just don't know how to go about sorting by somewhere in the middle of the string
 
  • #11
Do you mean you are putting all the information about a student into one string? No offense, but that's not a very good design.

A more reasonable way to do things would be to store the information about a student in a class, and then have an array (or list) of class instances.
 
  • #12
I'm using nextToken to read the 4 attributes of each student into an object 'student'
Then I add them to an array list one student at a time. So it's a number of students and each student is a string. I do have another class full of set and get methods for the 4 attributes but I'm not sure how to use it alongside reading the file in. I have one class that builds the GUI and reads the csv file, one class full of set and get methods and one class with the main that runs it all.
 
  • #13
Okay so I am pretty sure I've got each student in an arraylist as objects of class studentList.java which contains set and get methods for the 4 string attributes ID, name, phone, email.

The following code is the method that reads the csv file StudentContacts which is a file with ID, name, phone and email of a number of students. underneath the class declaration is this line

private ArrayList<StudentList> allStudents = new ArrayList<StudentList>();

which creates an array of instances of class StudentList i believe. The program runs through a GUI and output1 and output2 are just two textfields in tabs of a jtabbedpane so just ignore those. I've got most of it sorted out, but i think there is a problem when i load the arraylist. When i setText of the output jtextfields the info of the students displays fine. but at the end i have a print call to print the object arraylist of the students to the command prompt window. however the output is all screwed up. something like

[StudentList@53c015, StudentList@67ac19, StudentList@53ba3d etc etc]

i can't work out why it doesn't fill the array correctly.

Code:
public void loadFile()
    {
        try
        {
            FileInputStream fstream = new FileInputStream("StudentContacts.csv"); // Open the file
            DataInputStream list = new DataInputStream(fstream); // Get the object of DataInputStream
            BufferedReader br = new BufferedReader(new InputStreamReader(list));
            String strLine;
            StringTokenizer st;
            
            output1.append( String.format("%-20s%-30s%-20s%-20s\n\n", 
                    "Student ID", "Student Name", "Phone", "Email" ) );
            output2.append( String.format("%-20s%-30s%-20s%-20s\n\n", 
                    "Student ID", "Student Name", "Phone", "Email" ) );
            
            while ((strLine = br.readLine()) != null)  //Read File Line By Line 
            {
                st = new StringTokenizer(strLine, ","); 
 
                while(st.hasMoreTokens())
                {  
                    ID = st.nextToken();
                    name = st.nextToken();
                    phone = st.nextToken();
                    email = st.nextToken();
                    student = String.format("%-20s%-30s%-20s%-20s\n",
                            ID, name, phone, email );
                    allStudents.add(new StudentList( ID, name, phone, email));
                    
                    output1.append( student ); 
                    output2.append( student );
                    
                    
                }
                
            }
            System.out.print( allStudents );
            list.close(); //Close the input stream
        }

Then once i get it displaying correctly, adding new students is easy enough, then i should be able to sort them by attribute right? using the getmethods in studentList.java?

thanks guys
 
  • #14
okay another discovery.
Ive worked out why I am getting the strange output. because I am trying to print an object. then i thought i should just convert the arraylist of objects to strings in an array like this

Object[] array = students.toArray();

and then using a for statement like

Code:
for(int i =0;i<array.size();i++)
                {   
                    newList = students.get(i);
                    System.out.println(newList.getID()  + newList.getName()
                            + newList.getPhone() + newList.getEmail());
                }
in which newList is an instance of class StudentList by using the statement

StudentList newList = new StudentList();

but then the command prompt busted out an error saying canot find constructor of StudentList(); but then when i copy the argument of the StudentList method out of StudentList.java and put it in the statement above is shows on the IDE that its a forward reference and then says needs multiple ( and ; and identifiers.

Ive seen a few other code examples successfully print their arraylists after they are filled with objects. but i can't simulate any. and i can't check to see if the array is being filled correctly since i can't print its contents. so right now i guess the most important thing is being able to print the contents of my arraylist. once i can do that i can fiddle around and do more myself.

Thanks. Am calling it a night for now so i won't discover much more tonight.
 
  • #15
ProPatto16 said:
okay another discovery.
Ive worked out why I am getting the strange output. because I am trying to print an object. then i thought i should just convert the arraylist of objects to strings in an array like this

Object[] array = students.toArray();

and then using a for statement like

Code:
for(int i =0; i < array.size(); i++)
                {   
                    newList = students.get(i);
                    System.out.println(newList.getID()  + newList.getName()
                            + newList.getPhone() + newList.getEmail());
                }
in which newList is an instance of class StudentList by using the statement

StudentList newList = new StudentList();

First, the only place "array" appears in this loop is in the for condition; does that make any sense?

Second, there is no need to convert the attributes of your StudentList instances to an array of strings at all. Rather, if you have an ArrayList of instances of StudentList, called "students", you can print the output with something like

Code:
for(int i =0; i<students.size();i++)
                {   
                    System.out.println(students.get(i).getID()  + students.get(i).getName()
                            + students.get(i).getPhone() + students.get(i).getEmail());
                }

but then the command prompt busted out an error saying canot find constructor of StudentList();

Are you sure that the specified error comes from this snippet of code, and not, for example, from the following?

Code:
allStudents.add(new StudentList( ID, name, phone, email));

This line, taken from your previously posted version of the loadFile() method, requires the StudentList class to have a constructor with 4 input parameters for ID, name, phone and email.
 
  • #16
okay i tried using your for loop to print, but i can't quite get there because now i can't seem to fill my arrayList properly.
firstly note the StudentList class does indeed have a constructor. my command prompt is now giving me the same cannot find constructor error and its definitely in the line where i attempt to create the object of StudentList class.
The way i was using the get methods to retrieve the strings i think was wrong, because i wasnt first using the set method hah. ill post some snippets of the code and explain what i believe is happening.

this is StudentList.java
Code:
public class StudentList {
    private String ID;
    private String name;
    private String phone;
    private String email;

    public StudentList(String i, String n, String p, String e)
    {
        ID = i;
        name = n;
        phone = p;
        email = e;
    }

    public void setId(String i)
    {
        ID = i;
    }

    public String getId()
    {
        return ID;
    }
In that class there are exact repeats for setName() getName() setPhone() getPhone() setEmail() getEmail() i just didnt post them, didnt want repetitive code taking up space.

this is StudentListProgram.java
Code:
while ((strLine = br.readLine()) != null)  //Read File Line By Line 
            {
                st = new StringTokenizer(strLine, ","); 
 
                while(st.hasMoreTokens())
                {  
                    newList.setId(st.nextToken());
                    newList.setName(st.nextToken());
                    newList.setPhone(st.nextToken());
                    newList.setEmail(st.nextToken());
                    
                    student = String.format("%-20s%-30s%-20s%-20s\n",
                            getId(), getName(), getPhone(), getEmail() );
                    students.add(new StudentList( getId(), getName(), 
                            getPhone(), getEmail()));
                    
                    output1.append( student ); 
                    output2.append( student );
                    
                    
                }
                
                for(int i =0; i<students.size();i++)
                {   
                    System.out.println(students.get(i).getId()  + students.get(i).getName()
                            + students.get(i).getPhone() + students.get(i).getEmail());
                }

This is my while loop that reads the csv file line by line. I am 100% certain it is reading correctly, I've been using print methods to check.

What I am not sure about is the way I am using the setMethods. The other way i was doing it was declaring new strings in the loadFile() method above the while loop for ID, name, phone, and email. but then i figured if i don't set those parameters in StudentList using the set methods then i can't use the get methods to retrieve them. and i need to use the StudentList class this way. When i was using the strings ID, name, phone and email i just had ID = st.nextToken() so i figured to set the nextToken to the parameter in StudentList get methods then it needed to be the string argument for the methods. hope you can follow what i mean.

In the command prompt i get 9 errors. the first one is can't find constructor, then the other eight are errors saying can't find get methods. 4 get methods called twice makes the 8 errors. called once where i try to fill the array and once where i try to print it.

thats about it for now, ill keep at it, thank you.
 
  • #17
ProPatto16 said:
okay i tried using your for loop to print, but i can't quite get there because now i can't seem to fill my arrayList properly.
firstly note the StudentList class does indeed have a constructor. my command prompt is now giving me the same cannot find constructor error and its definitely in the line where i attempt to create the object of StudentList class.
The way i was using the get methods to retrieve the strings i think was wrong, because i wasnt first using the set method hah. ill post some snippets of the code and explain what i believe is happening.

this is StudentList.java
Code:
public class StudentList {
    private String ID;
    private String name;
    private String phone;
    private String email;

    public StudentList(String i, String n, String p, String e)
    {
        ID = i;
        name = n;
        phone = p;
        email = e;
    }

    public void setId(String i)
    {
        ID = i;
    }

    public String getId()
    {
        return ID;
    }
In that class there are exact repeats for setName() getName() setPhone() getPhone() setEmail() getEmail() i just didnt post them, didnt want repetitive code taking up space.

Get rid of the public keyword in front of your would-be constructor method :wink:

this is StudentListProgram.java
Code:
while ((strLine = br.readLine()) != null)  //Read File Line By Line 
            {
                st = new StringTokenizer(strLine, ","); 
 
                while(st.hasMoreTokens())
                {  
                    newList.setId(st.nextToken());
                    newList.setName(st.nextToken());
                    newList.setPhone(st.nextToken());
                    newList.setEmail(st.nextToken());
                    
                    student = String.format("%-20s%-30s%-20s%-20s\n",
                            getId(), getName(), getPhone(), getEmail() );
                    students.add(new StudentList( getId(), getName(), 
                            getPhone(), getEmail()));
                    
                    output1.append( student ); 
                    output2.append( student );
                    
                    
                }
                
                for(int i =0; i<students.size();i++)
                {   
                    System.out.println(students.get(i).getId()  + students.get(i).getName()
                            + students.get(i).getPhone() + students.get(i).getEmail());
                }

This is my while loop that reads the csv file line by line. I am 100% certain it is reading correctly, I've been using print methods to check.

What I am not sure about is the way I am using the setMethods. The other way i was doing it was declaring new strings in the loadFile() method above the while loop for ID, name, phone, and email. but then i figured if i don't set those parameters in StudentList using the set methods then i can't use the get methods to retrieve them. and i need to use the StudentList class this way. When i was using the strings ID, name, phone and email i just had ID = st.nextToken() so i figured to set the nextToken to the parameter in StudentList get methods then it needed to be the string argument for the methods. hope you can follow what i mean.

In the command prompt i get 9 errors. the first one is can't find constructor, then the other eight are errors saying can't find get methods. 4 get methods called twice makes the 8 errors. called once where i try to fill the array and once where i try to print it.

thats about it for now, ill keep at it, thank you.

8 of your get method calls aren't qualified with the name of the object reference that they belong to (i.e you need to have "newList.getName()" instead of "getName()" )

Additionally, it seems suspect to only check st.hasMoreTokens() once per loop pass, but call st.nextTokens() 4 times. What happens if the file is formatted correctly, but one line only has 3 tokens because the student didn't give an Email address?

Also, what are output1 and output2?
 
  • #18
of course, always need to use the class instance to call methods from that class, duhh. i removed the public keyword in front of StudentList(String i, String, n, String p, String e) but still getting the same error. ill do some looking up on how to create instances of classes with constructors. I am sure other people have come across this error.

As for the tokenizing strings, the input for a new student is entered through 4 jtextfields for each attribute and the string inputs can be anything except blank. so if the details arent there then it won't be passed back to the arraylist or saved back to the file.
 
  • #19
ProPatto16 said:
i removed the public keyword in front of StudentList(String i, String, n, String p, String e) but still getting the same error.

Did you make sure to recompile StudentList? I t works fine for me.
 
  • #20
Still got the same error but i worked it out. even with the public keyword left in. i was trying to create an instance of the class with an empty constructor where the constuctor in StudentList is 4 strings. so i needed

StudentList newList = new StudentList( "ID", "name", "phone", "email" );

instead of

StudentList newList = new StudentList();

because the constructor in StudentList is 4 strings.

Thanks for all your help! When i finish my degree ill be trawling these forums to try help out other kids like me :)
 

FAQ: NoSuchElementException when reading CSV file

What is a NoSuchElementException when reading CSV file?

A NoSuchElementException is an error that occurs when trying to access an element that does not exist in a collection or data structure. In the context of reading a CSV file, it means that the program is trying to read a value from a column or row that does not exist.

Why do I get a NoSuchElementException when reading a CSV file?

This error can occur for a few reasons. One possibility is that the CSV file is empty, so there are no elements to read. Another possibility is that the program is trying to read a column or row that does not exist in the CSV file. It could also be caused by a formatting issue in the CSV file.

How can I fix a NoSuchElementException when reading a CSV file?

The best way to fix this error is to check your code for any potential issues. Make sure that you are referencing the correct columns and rows in the CSV file. Also, check that the CSV file is properly formatted and contains the data you are trying to access. If the file is empty, you may need to handle that case separately in your code.

Can a NoSuchElementException be prevented when reading a CSV file?

Yes, there are steps you can take to prevent this error from occurring. First, make sure to thoroughly check your code for any potential issues, such as referencing the wrong columns or rows. Additionally, you can use try-catch blocks to handle any potential errors that may arise while reading the CSV file.

Is a NoSuchElementException a common error when working with CSV files?

Yes, this error can be common when working with CSV files, especially if the file is not properly formatted or if there are issues with the code. It is important to carefully check your code and handle any potential errors that may occur while reading the CSV file.

Similar threads

Replies
3
Views
1K
Replies
10
Views
2K
Replies
2
Views
3K
Replies
4
Views
12K
Replies
1
Views
1K
Replies
5
Views
8K
Back
Top