InputMissMatchException
I want to read data about MMORPG characters from a .txt file and then filter on experience (minimum experience). But I'm getting this exception, which I know the meaning of but I really don't understand what I'm doing wrong.
I'm not good at java, I'm a beginner actually. Can someone please explain this to me? Probably I'm doing something very stupid.
This is my code:
Karakter (Character):
import java.util.Scanner;
public class Karakter {
private String name;
private int experience;
private int maxHealthPoints;
private int healthPoints;
private int maxGreed;
private int greed;
public Karakter(String nm, int exp, int mHP, int hp, int mG, int g)
{
name = nm;
experience = exp;
maxHealthPoints = mHP;
healthPoints = hp;
maxGreed = mG;
greed = g;
}
public String toString()
{
String s = "";
s += getName();
s += getExperience();
s += getMaxHealthPoints();
s += getHealthPoints();
s += getMaxGreed();
s += getGreed();
return s;
}
public static Karakter read(Scanner sc)
{
String name = sc.next();
int experience = sc.nextInt();
int maxHealthPoints = sc.nextInt();
int healthPoints = sc.nextInt();
int maxGreed = sc.nextInt();
int greed = sc.nextInt();
return new Karakter(name, experience, maxHealthPoints, healthPoints, maxGreed, greed);
}
public boolean hasExperience(int min)
{
return experience >= min;
}
// returns true if Krakters have the same name
public boolean equals(Object other)
{
if(!(other instanceof Karakter))
{
return false;
}
else
{
Karakter that = (Karakter) other;
return that.name == this.name;
}
}
public String getName()
{
return name;
}
public int getExperience()
{
return experience;
}
public int getMaxHealthPoints()
{
return maxHealthPoints;
}
public int getHealthPoints()
{
return healthPoints;
}
public int getMaxGreed()
{
return maxGreed;
}
public int getGreed()
{
return greed;
}
}
Karakters (Characters):
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class Karakters {
private ArrayList<Karakter> kars = new ArrayList<Karakter>();
public void voegToe(Karakter kar)
{
if(!kars.contains(kar))
{
kars.add(kar);
}
}
// returns an arraylist of characters with exp >= minexp
public ArrayList<Karakter> karaktersVanaf(int minExperience)
{
Karakter kar = null;
for(int i = 0; i < kars.size(); i++)
{
if(kar.hasExperience(minExperience))
kars.add(kar);
}
return kars;
}
public static Karakters read(String infile)
{
Karakters k = new Karakters();
try
{
FileReader fr = new FileReader(infile);
Scanner sc = new Scanner(fr);
int aantal = sc.nextInt();
for(int i = 0; i < aantal ; i++)
{
Karakter kar = Karakter.read(sc);
k.kars.add(kar);
}
fr.close();
}
catch(IOException iox)
{
System.out.println(iox);
return null;
}
return k;
}
}
KarakterZoeker (Main method):
import java.util.ArrayList;
import java.util.Scanner;
public class KarakterZoeker {
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
Karakters kars = Karakters.read("infile.txt");
System.out.println("Welke experience wilt u minimaal?");
int minExp = sc.nextInt();
ArrayList<Karakter> s = kars.karaktersVanaf(minExp);
System.out.println(s.toString());
}
}
And this is the error:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at Karakter.read(Karakte开发者_运维知识库r.java:38)
at Karakters.read(Karakters.java:41)
at KarakterZoeker.main(KarakterZoeker.java:14)
these lines:
Karakter kar = Karakter.read(sc); (in Karakters)
int experience = sc.nextInt(); (in Karakter)
Karakters kars = Karakters.read("infile.txt"); (in KarakterZoeker)
this is the txt file:
2
name = Dursley
experience = 15
maxHealthPoints = 20
healthPoints = 10
maxGreed = 3
greed = 1
name = Aragorn
experience = 45
maxHealthPoints = 40
healthPoints = 30
maxGreed = 20
greed = 10
InputMismatchException
is thrown by a Scanner to indicate that the token retrieved does not match the pattern for the expected type, or that the token is out of range for the expected type.
So, my guess is that you are calling nextInt
when the next token isn't actually an Integer
.
EDIT
You need to be careful when reading that file, because you have labels that count as tokens. For instance, when you have:
maxHealthPoints = 20 ,
You have three tokens: "maxHealthPoints", "=", and "20". The problem is that you are ignoring both the label (before "=") and the equal sign. My advice? Read your file line by line and use the Scanner
to parse each line. Alternatively, remove the labels and the equal sign from the file, leaving just the values you want to extract.
Calling next()
twice fixed the problem. After that I got a NullPointerException
in my karaktersVanaf(minExp)
in Karakters. To fix this I added these lines to my code:
public ArrayList<Karakter> karaktersVanaf(int minExperience) throws FileNotFoundException
{
Scanner sc = new Scanner(new FileReader("infile.txt")); // --------line 1
Karakter kar = Karakter.read(sc); // ------------ line 2
for(int i = 0; i < kars.size(); i++)
{
if(kar.hasExperience(minExperience))
kars.add(kar);
}
return kars;
}
But now I'm seeing the InputMissMatschException
again! I don't know what I'm doing wrong! I may be doing something totally wrong so be ready to laugh.
By th way, I don't have 15 experience points yet, that's why I can't vote for you just now. I will do that as soon as I can do so.
The problem is that on this line:
int experience = sc.nextInt();
You are trying to read a "int" but what the scanner reads is a string "experience"
From this line in your .txt file:
experience = 15
So you have to read two strings ( 1st is "experience" and 2nd is "=" ) and then you will be able to read an int ( 15 ) and so on.
The first one didn't failed, because name
was assigned a String, but if you log what you read, you've got: "name" instead of the real name.
An alternative is to let the ResourceBundle
class do the read for you. Or even the Properties
class.
With ResourceBundle you would do something like:
ResourceBundle bundle = ResourceBundle.getBundle("Karakters");
String exp = bundle.getString("experience");
int experience = Integer.parseInt( exp );
And you would have to name that as: Karakters.properties
EDIT
I have added a sample on how I would do this using ResouceBundle
Each time your reader does a nextInt() or nextString(), it doesn't read the next line, it reads the next characters separated by whitespace (space or newline). The simplest way to fix your problem would be to remove the "name =", "experience =", and just put the unique data on each line.
So your file would look like:
2
Dursley
15
20
10
3
1
Aragorn
45
40
30
20
10
And then your code will work as is.
I have coded a way to read using ResourceBundle.
I leave it here, I hope you find it useful:
import java.util.*;
public class Ktr {
public static void main( String [] args ) {
ResourceBundle b = ResourceBundle.getBundle("k");
String names = b.getString("names");
List<K> l = new ArrayList<K>();
for( String name : names.split(",")){
l.add( K.read( name, b ));
}
System.out.println( l );
}
}
class K {
private String name;
private int maxHealthPoints;
private int maxGreed;
// etc..
public static K read( String name, ResourceBundle b ) {
K k = new K();
k.name = name;
k.maxHealthPoints =
Integer.parseInt(b.getString( name + ".maxHealthPoints") );
k.maxGreed =
Integer.parseInt(b.getString( name + ".maxGreed") );
// you get the idea
return k;
}
public String toString() {
return String.format("%s{maxHealthPoints=%d, maxGreed=%d}",
name, maxHealthPoints, maxGreed);
}
}
k.properties
names=Dursley,Aragorn
Dursley.maxHealthPoints=20
Dursley.maxGreed=3
Aragorn.maxHealthPoints=40
Aragorn.maxGreed=20
Output:
java Ktr
[Dursley{maxHealthPoints=20, maxGreed=3}, Aragorn{maxHealthPoints=40, maxGreed=20}]
精彩评论