0

I am trying to run the below file TemplateMaker.java in Netbeans IDE 8.0.2 and am running into the following error message. Netbeans shows no red indicators for me to fix. Please help.

Exception in thread "main" java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Scanner.java:907)
    at java.util.Scanner.next(Scanner.java:1416)
    at templatemaker.TemplateMaker.processLine(TemplateMaker.java:48)
    at templatemaker.TemplateMaker.processLineByLine(TemplateMaker.java:35)
    at templatemaker.TemplateMaker.main(TemplateMaker.java:17)
Java Result: 1

Here is my source code:

package templatemaker;


import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;


public class TemplateMaker {

        public static void main(String [] args)
 throws IOException {
    TemplateMaker parser = new TemplateMaker("Book1.txt");
    parser.processLineByLine();
    log("Done.");
  }

  /**
   Constructor.
   @param aFileName full name of an existing, readable file.
  */
  public TemplateMaker(String aFileName){
    fFilePath = Paths.get(aFileName);
  }


  /** Template method that calls {@link #processLine(String)}.
     * @throws java.io.IOException */
  public final void processLineByLine() throws IOException {
    try (Scanner scanner =  new Scanner(fFilePath, ENCODING.name())){
      while (scanner.hasNextLine()){
        processLine(scanner.nextLine());
      }      
    }
  }


  protected void processLine(String aLine){
    //use a second Scanner to parse the content of each line 
    Scanner scanner = new Scanner(aLine);
    scanner.useDelimiter("=");
    if (scanner.hasNext()){
      //assumes the line has a certain structure
      String name = scanner.next();
      String value = scanner.next();
      log("Name is : " + quote(name.trim()) + ", and Value is : " + quote(value.trim()));
    }
    else {
      log("Empty or invalid line. Unable to process.");
    }
  }

  // PRIVATE 
  private final Path fFilePath;
  private final static Charset ENCODING = StandardCharsets.UTF_8;  

  private static void log(Object aObject){
    System.out.println(String.valueOf(aObject));
  }

  private String quote(String aText){
    String QUOTE = "'";
    return QUOTE + aText + QUOTE;
  }
} 
3
  • 5
    You check with hasNext() once, and then read twice. Not a good idea. Commented Jan 7, 2015 at 20:54
  • 4
    Why don't you use the debugger and step through the code? Commented Jan 7, 2015 at 20:55
  • Not even a debugger needed. Normal console output would be enough ;) Commented Jan 7, 2015 at 21:40

2 Answers 2

1

Your processLine() is expecting a "name=value" pair. And as MightyPork said you are checking hasNext() once, and then read twice. So if that line does not have an = symbol this will break as scanner wont get the next() token. You should add two hasNext() checks. Ideally you dont need a scanner here. Since you are always expecting two tokens delimited by = you can simply rely on java.util.StringTokenizer as

protected void processLine(String aLine){
    StringTokenizer st = new StringTokenizer(aLine, "=");
    if(st.countTokens() == 2) {
        log("Name is : " + quote(st.nextToken().trim()) + ", and Value is : " + quote(st.nextToken().trim()));
    } else {
        log("Empty or invalid line. Unable to process.");
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

As the stacktrace indicates, the exception was thrown when scanner.next() was called

at java.util.Scanner.next(Scanner.java:1416)

if (scanner.hasNext()){
      //assumes the line has a certain structure
      String name = scanner.next(); // checked by hasNext()
      String value = scanner.next(); // not checked by hasNext()
      log("Name is : " + quote(name.trim()) + ", and Value is : " + quote(value.trim()));
}

The error must be in the second .next(). You check if the scanner has a next token, but you call .next() twice. So I assume there is 1 token left and you read twice. Also from the API the next() method:

Throws:
    NoSuchElementException - if no more tokens are available
    IllegalStateException - if this scanner is closed

You can check that easily by adding a System.out.println statement and check what's the last one before the exception (after the first or second call of next())

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.