Reputation: 109
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;
}
}
Upvotes: 0
Views: 183
Reputation: 8499
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.");
}
}
Upvotes: 1
Reputation: 1129
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())
Upvotes: 0