Java で開発している犬小屋システムにブール値を実装しましたが、ファイルからデータをロードするときに InputMismatchError が発生します。
私は何度か読んで解決しようとしましたが、私が試みている解決策はうまくいきません。これまでのところ:
- 読み込みメソッド (初期化) を再構築して、データを適切かつ正しい順序で読み込み、それを newPet (ローカル変数) に正しい順序で割り当てます。
次に、.txt ファイル (以下) を読み、すべてが正しいデータに対応していること、文字列が文字列として読み取られていること、int が int として読み取られていることなどを確認しました。
ここで InputMismatch による問題を特定できる人はいますか?
エラーは次のとおりです。
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.nextBoolean(Unknown Source)
at KennelDemo.initialise(KennelDemo.java:79)
at KennelDemo.main(KennelDemo.java:337)
79行目と337行目は次のとおりです。
boolean mutualBoolean = infile.nextBoolean(); //and
demo.initialise();
メインクラス(長くなってすみません)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;
public class KennelDemo {
private String filename; // holds the name of the file
private Kennel kennel; // holds the kennel
private Scanner scan; // so we can read from keyboard
private String tempFileName;
private String dogsFile = "dogs.txt";
private String catsFile = "cats.txt";
/*
* Notice how we can make this private, since we only call from main which
* is in this class. We don't want this class to be used by any other class.
*/
private KennelDemo() {
scan = new Scanner(System.in);
boolean fileCorrect = false;
do {
System.out.print("Which animal are you looking to check into the kennel?: " + "\n");
System.out.println("Dog");
System.out.println("Cat");
tempFileName = scan.next();
if(tempFileName.toLowerCase().equals("dog") || tempFileName.toLowerCase().equals("cat")) {
filename = tempFileName.toLowerCase().equals("dog") ? dogsFile : catsFile;
fileCorrect = true;
}
else {
System.out.println("That is not a valid filename, please enter either 'Dog' or 'cat' in lowercase.");
}
}
while(!fileCorrect);
}
/*
* initialise() method runs from the main and reads from a file
*/
private void initialise() {
kennel = new Kennel();
System.out.println("Using file " + filename);
// Using try-with-resource (see my slides from session 15)
try(FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
Scanner infile = new Scanner(br)){
String kennelName = infile.nextLine();
int kennelSize = infile.nextInt();
infile.nextLine();
kennel.setCapacity(kennelSize);
int numPets = infile.nextInt();
infile.nextLine();
kennel.setName(kennelName);
for(int i=0; i < numPets; i++){
String PetName = infile.nextLine();
int numOwners = infile.nextInt();
infile.nextLine();
ArrayList<Owner> owners = new ArrayList<>();
for(int oCount=0; oCount < numOwners; oCount++){
String name = infile.nextLine();
String phone = infile.nextLine();
Owner owner = new Owner(name, phone);
owners.add(owner);
}
boolean mutualBoolean = infile.nextBoolean();
infile.nextLine();
String favFood = infile.nextLine();
infile.nextLine();
int feedsPerDay = infile.nextInt();
Pet Pet = new Pet(PetName, owners, mutualBoolean, favFood, feedsPerDay);
kennel.addPet(Pet);
}
} catch (FileNotFoundException e) {
System.err.println("The file: " + " does not exist. Assuming first use and an empty file." +
" If this is not the first use then have you accidentally deleted the file?");
} catch (IOException e) {
System.err.println("An unexpected error occurred when trying to open the file " + filename);
System.err.println(e.getMessage());
}
}
/*
* runMenu() method runs from the main and allows entry of data etc
*/
private void runMenu() {
String response;
do {
printMenu();
System.out.println("What would you like to do:");
scan = new Scanner(System.in);
response = scan.nextLine().toUpperCase();
switch (response) {
case "1":
admitPet();
break;
case "2":
changeKennelName();
break;
case "3":
printPetsWithBones();
break;
case "4":
searchForPet();
break;
case "5":
removePet();
break;
case "6":
setKennelCapacity();
break;
case "7":
printAll();
break;
case "Q":
break;
default:
System.out.println("Try again");
}
} while (!(response.equals("Q")));
}
private void setKennelCapacity() {
// set the boolean to check if the user REALLY wants to change the kennel size. We can never be too careful.
// boolean doContinue = false;
// Turns out the boolean does nothing, go figure.
// Still the error check works perfectly, now just a case of losing the temporary data if the program isn't closed through the menu.
// Kennel currently doesn't save until you use "q" at the menu to save the information. Possible solutions?
// Hello? Is this thing on?
int currentKennelCapacity = kennel.getCapacity();
System.out.println("The current kennel holds " + currentKennelCapacity + ", are you sure you want to change the current kennel size?");
String userWantsToContinue;
userWantsToContinue = scan.nextLine().toUpperCase();
if(userWantsToContinue.equals("Y")){
// doContinue = true;
System.out.print("Please enter the new size of the kennel you'd like: ");
int max = scan.nextInt();
scan.nextLine();
kennel.setCapacity(max);
System.out.println("The new kennel size is " + max + ", we'll now return you to the main menu. Please make sure the quit the program at the end of your session to save any changes. \n");
}
else System.out.println("No problem, we'll return you back to the main menu. \n");
//Duplicate code that caused an error when running through the conditions above, saved in case of future reference.
/* System.out.print("Enter max number of Pets: ");
int max = scan.nextInt();
scan.nextLine();
kennel.setCapacity(max);
*/
}
private void printPetsWithBones() {
Pet[] PetsWithBones = kennel.obtainDogsWhoLikeBones();
System.out.println("Pets with bones: ");
for (Pet d: PetsWithBones){
System.out.println("Pet name: " + d.getName());
}
}
/*
* printAll() method runs from the main and prints status
*/
private void printAll() {
Pet[] allPets = kennel.displayAllPets();
for (Pet p: allPets){
System.out.println("Animal name: " + p.getName());
System.out.println("Original owner(s): " + p.getOriginalOwners());
if(filename.equals(dogsFile)){
System.out.println("Do they like bones? " + Dog.getLikesBones());
}
else if(filename.equals(catsFile)){
System.out.println("Can they share a run? " + Cat.getShareRun());
}
System.out.println("Favourite food: " + p.getFavouriteFood());
System.out.println("Feeds per day: " + p.getFeedsPerDay());
System.out.println("====================================");
}
}
/*
* save() method runs from the main and writes back to file
*/
private void save() {
try(FileWriter fw = new FileWriter(filename);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter outfile = new PrintWriter(bw);){
outfile.println(kennel.getName());
outfile.println(kennel.getCapacity());
outfile.println(kennel.getNumOfPets());
Pet[] Pets = kennel.obtainAllPets();
for (Pet d: Pets){
outfile.println(d.getName());
Owner[] owners = d.getOriginalOwners();
outfile.println(owners.length);
for(Owner o: owners){
outfile.println(o.getName());
outfile.println(o.getPhone());
}
// TODO outfile.println(d.getLikesBones());
outfile.println(d.getFeedsPerDay());
outfile.println(d.getFavouriteFood());
}
} catch (IOException e) {
System.err.println("Problem when trying to write to file: " + filename);
}
}
private void removePet() {
System.out.println("which Pet do you want to remove");
String Pettoberemoved;
Pettoberemoved = scan.nextLine();
kennel.removePet(Pettoberemoved);
}
private void searchForPet() {
String allNames = kennel.getName();
System.out.println("Current pet in the kennel: " + allNames + "\n");
System.out.println("Which pet would you like to get the details for?");
String name = scan.nextLine();
Pet Pet = kennel.search(name);
if (Pet != null){
System.out.println(Pet.toString());
} else {
System.out.println("Could not find Pet: " + name);
}
}
private void changeKennelName() {
String name = scan.nextLine();
kennel.setName(name);
}
private void admitPet() {
boolean mutualBoolean = false;
if(filename.equals(dogsFile)){
System.out.println("enter on separate lines: name, owner-name, owner-phone, do they like bones?, favourite food, number of times fed");
}
else if(filename.equals(catsFile)){
System.out.println("enter on separate lines: name, owner-name, owner-phone, can they share a run?, favourite food, number of times fed");
}
String name = scan.nextLine();
ArrayList<Owner> owners = getOwners();
if(filename.equals(dogsFile)){
System.out.println("Does he like bones? (Y/N)");
}
else if(filename.equalsIgnoreCase(catsFile)){
System.out.println("Can the cat share a run? (Y/N)");
}
String booleanCheck;
booleanCheck = scan.nextLine().toUpperCase();
if (booleanCheck.equals("Y")) {
mutualBoolean = true;
}
System.out.println("What is his/her favourite food?");
String fav;
fav = scan.nextLine();
System.out.println("How many times is he/she fed a day? (as a number)");
int numTimes;
numTimes = scan.nextInt(); // This can be improved (InputMismatchException?)
numTimes = scan.nextInt();
Pet newPet = new Pet(name, owners, mutualBoolean, fav, numTimes);
kennel.addPet(newPet);
System.out.println("Pet " + newPet.getName() + " saved.");
// Save when you add new Pet in case the program isn't closed via the correct menu.
// Everything will still save when case "q" is used though.
save();
}
private ArrayList<Owner> getOwners() {
ArrayList<Owner> owners = new ArrayList<Owner>();
String answer;
do {
System.out
.println("Enter on separate lines: owner-name owner-phone");
String ownName = scan.nextLine();
String ownPhone = scan.nextLine();
Owner own = new Owner(ownName, ownPhone);
owners.add(own);
System.out.println("Another owner (Y/N)?");
answer = scan.nextLine().toUpperCase();
} while (!answer.equals("N"));
return owners;
}
private void printMenu() {
if(filename.equals(catsFile)) {
System.out.println("1 - add a new cat ");
System.out.println("2 - set up Kennel name");
System.out.println("4 - search for a cat");
System.out.println("5 - remove a cat");
System.out.println("6 - set kennel capacity");
System.out.println("7 - print all cats");
System.out.println("q - Quit");
}
else if(filename.equals(dogsFile)) {
System.out.println("1 - add a new dog ");
System.out.println("2 - set up Kennel name");
System.out.println("3 - print all dogs who like bones");
System.out.println("4 - search for a dog");
System.out.println("5 - remove a dog");
System.out.println("6 - set kennel capacity");
System.out.println("7 - print all dogs");
System.out.println("q - Quit");
}
}
// /////////////////////////////////////////////////
public static void main(String args[]) {
System.out.println("**********HELLO***********");
KennelDemo demo = new KennelDemo();
demo.initialise();
demo.runMenu();
demo.printAll();
demo.save();
System.out.println("***********GOODBYE**********");
}
}
そして、ここから読み取られる.txtファイルは次のとおりです。
DogsRUs // kennel name
20 // capacity
3 // number of pets
Rover //pet name
2 // number of owners
Chris Loftus // first owner
1234 // phone number
Pete Hoskins // second owner
2222 // phone number
1 // boolean for mutualBoolean
biscuits // favourite food
// NOTE: for some reason favFood wasn't being added but it wasn't causing an error at all, it's the boolean that's throwing the input error. Structure above repeats for the data below.
Dinky
1
James Bond
007007
1
Gold fingers
catTest
1
Billy
456789
1
Curry
明らかに問題はブール値が読み込まれていることですが、残念ながら解決策がまったくわかりません。MutualBoolean が likeBones のとき (元々、このプログラムは犬や猫ではなく、犬をチェックインするためだけに使用されていました)、問題なく動作していました。
使用されている相互ブール値を継承するために使用したコードは次のとおりです
import java.util.ArrayList;
public class Pet {
protected ArrayList<Owner> originalOwners;
protected boolean mutualBoolean;
protected String petName;
protected String favFood;
protected int foodPerDay;
public Pet(String name, ArrayList<Owner> owners, boolean mutualBoolean, String food, int mealsPerDay) {
petName = name;
this.favFood = food;
this.foodPerDay = mealsPerDay;
originalOwners = new ArrayList<Owner>();
for(Owner o: owners){
Owner copy = new Owner(o.getName(), o.getPhone());
originalOwners.add(copy);
}
this.mutualBoolean = mutualBoolean;
}
public String getName() {
return petName;
}
public void setName(String newName) {
petName = newName;
}
/*protected boolean mutualBoolean() {
return mutualBoolean;
}*/
/**
* Returns a copy of the original owners
* @return A copy of the original owners as an array
*/
public Owner[] getOriginalOwners(){
Owner[] result = new Owner[originalOwners.size()];
result = originalOwners.toArray(result);
return result;
}
/**
* How many times a day to feed the dog
* @param feeds The number of feeds per day
*/
public void setFeedsPerDay(int feeds){
foodPerDay = feeds;
}
/**
* The number of feeds per day the dog is fed
* @return The number of feeds per day
*/
public int getFeedsPerDay(){
return foodPerDay;
}
/**
* What's his favourite food?
* @param food The food he likes
*/
public void setFavouriteFood(String food){
favFood = food;
}
/**
* The food the dog likes to eat
* @return The food
*/
public String getFavouriteFood(){
return favFood;
}
/**
* Note that this only compares equality based on a
* dog's name.
* @param The other dog to compare against.
*/
@Override
public boolean equals(Object obj) { // Generated by Eclipse to be more robust
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (petName == null) {
if (other.petName != null)
return false;
} else if (!petName.equals(other.petName))
return false;
return true;
}
/**
* A basic implementation to just return all the data in string form
*/
public String toString() {
return "Dog name:" + petName + "Original Owner:" + originalOwners + "Favfood:" + favFood
+ "FoodPerDay:" + foodPerDay;
}
}
そして犬クラス
import java.util.ArrayList;
public class Dog extends Pet {
public static boolean likesBones;
public Dog(String name, ArrayList<Owner> owners, String food, int mealsPerDay, boolean likeBones) {
super(name, owners, likeBones, food, mealsPerDay);
Dog.likesBones = likeBones;
}
/**
* Does the dog like bones?
* @return true if he does
*/
public static boolean getLikesBones() {
return likesBones;
}
}