Hello,
Am writing java, using netbeans,
For what should be a simple try.. catch with a while loop, im 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. theres 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 im 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 :)

Related Engineering and Comp Sci Homework Help News on Phys.org
Mark44
Mentor
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.

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.

Nevermind guys,
just changed my program to use a fileInputStream :)

gabbagabbahey
Homework Helper
Gold Member
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

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 im not sure how i can be using it incorrectly. granted i may not know every exact detail of what is happening, since im still very much in the learning stages.

Mark44
Mentor
Rather than describing in words the code you tried, show it to us.

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

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

Thanks

Mark44
Mentor
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?

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 dont know how to go about sorting by somewhere in the middle of the string

Mark44
Mentor
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.

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.

Okay so im pretty sure ive 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. ive 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

[[email protected], [email protected], [email protected] etc etc]

i cant work out why it doesnt 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
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" ) );

{
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

okay another discovery.
Ive worked out why im getting the strange output. because im 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 cant simulate any. and i cant check to see if the array is being filled correctly since i cant 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 wont discover much more tonight.

gabbagabbahey
Homework Helper
Gold Member
okay another discovery.
Ive worked out why im getting the strange output. because im 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.

okay i tried using your for loop to print, but i cant quite get there because now i cant 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 definately 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() );
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. Im 100% certain it is reading correctly, ive been using print methods to check.

What im not sure about is the way im 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 dont set those parameters in StudentList using the set methods then i cant 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 cant find constructor, then the other eight are errors saying cant 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.

gabbagabbahey
Homework Helper
Gold Member
okay i tried using your for loop to print, but i cant quite get there because now i cant 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 definately 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

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() );
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. Im 100% certain it is reading correctly, ive been using print methods to check.

What im not sure about is the way im 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 dont set those parameters in StudentList using the set methods then i cant 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 cant find constructor, then the other eight are errors saying cant 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?

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. im 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 wont be passed back to the arraylist or saved back to the file.

gabbagabbahey
Homework Helper
Gold Member
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.

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" );

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 :)