Norse
Norse

Reputation: 5757

Multiple input.next() inside of a while(input.hasNext()) triggers NoSuchElementException in Java

I have a text file

Jim,A,94
Pam,B-4,120
Michael,CC,3

I want to save each token delimited by a comma to a string variable. I have this code:

File f = new File(filename);
Scanner input = new Scanner(f);
input.useDelimiter(",");

while (input.hasNext())
{
    String s1 = input.next();
    String s2 = input.next();
    String s3 = input.next();
}

input.close();

But this keeps triggering NoSuchElementException. What am I doing wrong here?

Upvotes: 1

Views: 53

Answers (3)

Giorgi Tsiklauri
Giorgi Tsiklauri

Reputation: 11138

You have a custom delimiter ,. So, your input string is delimitted by , and everything before and after that character will constitute a token returned by .next();.

\n escape character, that is present in your input as a new line character, is also a character:

\n (linefeed LF, Unicode \u000a)

and it's being read as part of your token.

Upvotes: 1

Jim Garrison
Jim Garrison

Reputation: 86774

This is a subtle quirk of how Scanner#next() works. That method looks for a "token", which is everything between occurrences of the delimiter character. The default delimiter is "\\p{javaWhitespace}+", which includes \n, \r.

You changed the delimiter to a comma, and ONLY the comma. To your Scanner the input looks like this:

Jim,A,94\nPam,B-4,120\nMichael,CC,3

The tokens as seen by your scanner are:

Jim
A
94\nPam
B-4
120\nMichael
CC
3

That's only 7 tokens, so you hit the end of input before satisfying all the next() invocations.

The simplest fix is to set the delimiter to "[," + System.lineSeparator() + "]".

However, Scanner is the cause of endless errors and frustration for new developers, and should be deprecated and banished (that won't happen because of the existing code base). What you should be doing is reading entire lines and then parsing them yourself.

Upvotes: 2

Marco Tizzano
Marco Tizzano

Reputation: 1916

Here is another way to achieve what you are trying to do:

File f = new File(filename);
Scanner input = new Scanner(f);

while (input.hasNext()) {
    String[] sarray = input.nextLine().split(",");
    for (String s : sarray ) {
        System.out.println(s);
    }
}

Of course, that can be improved, but basically I suggest that you use the Scanner to read the file line by line and then you split by comma delimiter.

Upvotes: 0

Related Questions