String Tokenizer Help

Dinh

Limp Gawd
Joined
Aug 27, 2006
Messages
194
I've been messing around with Java for the last two weeks and created this simple flat file database login, but I've stumbled across this error that has stumped me.

Basically, I'm trying to load a text file, break down the string using the StringTokenizer,
and load it into an 2D Array.

Code:
Exception in thread "main" java.util.NoSuchElementException
        at java.util.StringTokenizer.nextToken(StringTokenizer.java:332)
        at loginController.loadUserDatabase(loginController.java:36)
        at FinalED.main(FinalED.java:52)
Press any key to continue...

Main
Code:
public class FinalED 
{

   loginController login = new loginController();
    public static void main(String[] args) 
    {

      login.loadUserDatabase();

    }

loginController
Code:
import java.util.*;

import java.io.*; 


public class loginController {
	
	public static String[][] credentials = new String[20][3];
	

    public static void loadUserDatabase()
    {
    
    	try
    	{
    	
			Scanner loadUserDatabase = new Scanner(new File("users.db"));
		
    	
    		
    		while (loadUserDatabase.nextLine() != null)
    			
    		{	
    			String dbRecord = loadUserDatabase.nextLine();
    			StringTokenizer dbRead = new StringTokenizer(dbRecord, ":");
    			for(int i=0;i<3;i++)
				{
				//Username
				credentials[i][0]= dbRead.nextToken(); //line 36
				
				//Password
				credentials[i][1]= dbRead.nextToken();
				
				//Access Level
				credentials[i][2]= dbRead.nextToken();
				
				}
					
    		}
    		
    	}
    	catch(IOException e)
    	{
    		
    	}	
    }
    
 	//Simple debug
    public static void checkCredentials()
    {
    	System.out.println(credentials[0][0] +credentials[0][1] +credentials[0][2] );
    }
    
    
}
 
change
while (loadUserDatabase.nextLine() != null)
to
while (loadUserDatabase.hasNextLine())

you should realize the way you have it you're ignoring the first line of the file. if that is necessary, then you need to call loadUserDatabase.nextLine() once before your while loop (of course, you ought to call hasNextLine() for that as well).

the javadocs indicate why nextLine() will throw a NoSuchElementException:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Scanner.html#nextLine()

// on a side note, they must have changed the forum time cuz it appears i posted first, but i didn't ;)


edit, i misread which part was giving you an error, though my point is valid about calling nextLine() for the while loop condition, it depends on your file format.

just do
String[] parts = dbRecord.split(":");
and don't bother with the tokenizer. then you can check parts.length to see if the number of parts is correct.
 
So the J2SE spec says that StringTokenizer.nextToken throws:

"NoSuchElementException - if there are no more tokens in this tokenizer's string."

Can you System.out.println(dbRecord) for us?
 
The bigger problem is that your inner loop logic is almost certainly wrong.

Code:
String dbRecord = loadUserDatabase.nextLine();
StringTokenizer dbRead = new StringTokenizer(dbRecord, ":");
for(int i=0;i<3;i++)
{
    //Username
    credentials[i][0]= dbRead.nextToken(); //line 36

    //Password
    credentials[i][1]= dbRead.nextToken();

    //Access Level
    credentials[i][2]= dbRead.nextToken();

}

The above code indicates that each line of users.db is of the form:

Code:
A:B:C:D:E:F:G:H:I

and that you want to store those tokens in credentials as:

Code:
credentials[0][0] = A;
credentials[0][1] = B;
credentials[0][2] = C;
credentials[1][0] = D;
credentials[1][1] = E;
credentials[1][2] = F;
credentials[2][0] = G;
credentials[2][1] = H;
credentials[2][2] = I;

Furthermore, your code indicates that you want those 9 array locations overwritten by the tokens of each subsequent line. Nothing at all is ever stored in credentials[3-19].

Is that your intent?
 
[amromousa]
> StringTokenizer is also deprecated, right?

Nope, and for one important reason: it doesn't use regular expressions to tokenize input; it uses simple (literal) character matching. That may seem like a weakness, but regexs can be slow. If you're tokenizing a lot of input and your delimiter is simple, you can see a huge performance boost by using StringTokenizer instead of String.split et. al.

EDIT: Wow, the forum is seriously broken. I made this post at 7:25 PM MST in response to amromousa's, but it got a timestamp of 7:01 and appeared way up in the thread, before the post I was replying to. Whack.
 
StringTokenizer is also deprecated, right?

It's not deprecated, however it is not recommended and will probably be come depericated in the future though I doubt it will ever be removed from J2SE due to the mass amounts of legacy code that depends on it.

Best practices recommend using regex instead, such as String instance methods split() and match(String)

Edit:

For some reason my post has an earlier timestamp than the one I was replying to :confused:
 
The bigger problem is that your inner loop logic is almost certainly wrong.

Furthermore, your code indicates that you want those 9 array locations overwritten by the tokens of each subsequent line. Nothing at all is ever stored in credentials[3-19].

Is that your intent?

Well I was editing it so it would only take the first line out of

Code:
Eddie:password:1
Rob:123456:2
Steve:passwords:2

so the array should look like this :

Code:
credentials[0][1] = Eddie;
credentials[0][2] = password;
credentials[0][3] = 1;

I forgot to change the size of the array back, but it shouldn't matter. And yes, thanks for pointing that out that my logic is wrong. I've been trying to cram alot and get to the fun stuff :D, but that doesn't come without work.
 
Back
Top