keep getting this java.util.NoSuchElementException: No line found

101 Views Asked by At

I get this error when I try to read a text file.

This is my code for the items reader:

File itemFile = new File("src/items.txt");
Scanner itemReader = null;
try {
    itemReader = new Scanner(itemFile);
    //roomReader = new Scanner(roomFile);
}
catch (FileNotFoundException e) {
    System.out.println("The Items.txt file has not been found");
}
// read one value at a time
if (itemReader != null) {
    itemReader.useDelimiter("\\|");
    while (itemReader.hasNext()) {
        String itemName = itemReader.next();
        String itemDesc = itemReader.next();
        String itemLocation = itemReader.next();

        // Process the item data
        Item item = new Item(itemName, itemDesc, itemLocation);
        Item.addItem(item);
        itemReader.nextLine(); // Move to the next line
    }
    itemReader.close();
}

This is the stack trace as well:

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.base/java.util.Scanner.nextLine(Scanner.java:1656)
    at Driver.main(Driver.java:86)

This is my items.txt file as a test:

beep|An old beep|3
gun|An old gun with no bullets|2
stun|HUNG|1

I tried checking the format and I tried rewriting the text file.

1

There are 1 best solutions below

0
On

Your delimiter pattern does not account for newlines. So your file is read as:

itemName    itemDesc         itemLocation    IGNORED_INPUT_nextLine
---------------------------------------------------------------------------
beep        An old beep      3\ngun          An old gun with no bullets|2\n
stun        HUNG             1\n             

At this point, we fail to read a token. If an \n existed after the final 1, it would be consumed by the itemLocation regardless, as it is not a part of the delimiter pattern. Remember, the delimiter pattern isn't just what you want to split tokens by, but also what should not be included inside of a token. The java-specific default is "\\p{javaWhitespace}+" which is almost equivalent to \\s+. You of course don't want to include generic whitespace, but rather just newlines for delimiters (such that they are not included in your tokens). A rough approach:

itemReader.useDelimiter("[\r\n]+|\\|"); //note |\\| meaning "or a single |"

This will allow you to ignore those newlines, and appropriately finish your loop:

itemName    itemDesc                      itemLocation    IGNORED_INPUT_nextLine
--------------------------------------------------------------------------------
beep        An old beep                   3               \n
gun         An old gun with no bullets    2               \n
stun        HUNG                          1               \n             

A simpler approach may be instead just reading the lines flat-out, and then parsing the lines individually:

//zero need for itemReader.useDelimiter
while (itemReader.hasNextLine()) {
    String line = itemReader.nextLine();
    String spl = line.split("\\|");
    //note our implicit assumption (each line has 3 elements) is much more explicit now!
    String itemName = spl[0];
    String itemDesc = spl[1];
    String itemLocation = spl[2];
    //...
}

Now you also avoid running afoul of the latest JDK code for parsing line-by-line (whether it is \n, \r\n, \u2028, or so on).