简体   繁体   中英

Reading Data from Multiple txt Files in Java

I'm a beginner taking Intro to Computer Science and I'm working with java. I get the following error in this program when trying to read from multiple txt files in the getLetterGrade method:

Exception in thread "main" java.lang.IllegalStateException: Scanner closed

import java.util.Scanner;
import java.io.*;

public class Exam
{
    private int grade;
    private float examAvg;
    private String name;
    private File exam1Data;
    private File exam2Data;
    private File namesData;
    private Scanner inFileExam1;
    private Scanner inFileExam2;
    private Scanner inFileName;

    //constructor
    public Exam() throws IOException
    {
        exam1Data = new File("exam1.txt");
        exam2Data = new File("exam2.txt");
        namesData = new File("names.txt");
        inFileExam1 = new Scanner(exam1Data);
        inFileExam2 = new Scanner(exam2Data);
        inFileName = new Scanner(namesData);
    }

public float getExam1Avg()
{
examAvg = 0;

while (inFileExam1.hasNext()) {
grade = inFileExam1.nextInt();
examAvg += grade;
}
inFileExam1.close();
examAvg = (float)(examAvg / 25.0);
return examAvg;
}

public float getExam2Avg()
{
examAvg = 0;

while (inFileExam2.hasNext()) {
grade = inFileExam2.nextInt();
examAvg += grade;
}
inFileExam2.close();
examAvg = (float)(examAvg / 25.0);
return examAvg;
}

    //method that finds the letter grade given a student name and
    //the exam number
    public char getLetterGrade(String inputName, int examNum)
    {
        char letter;
        int count = 1;

        //inputName = inputName.toLowerCase();

        do {
            if (inFileName.hasNext()){
                name = inFileName.nextLine();
            }
            count++;
        } while (inFileName.hasNext() && !name.equalsIgnoreCase(inputName));

        inFileName.close();

        if (!name.equalsIgnoreCase(inputName)) {
            return 'x';
        }

        if (examNum == 1) {
            for (int i = 1; i <= count && inFileExam1.hasNextInt(); i++) {
                grade = inFileExam1.nextInt();
            }
            inFileExam1.close();
        }
        else if (examNum == 2) {
            for (int i = 1; i <= count && inFileExam2.hasNextInt(); i++) {
                grade = inFileExam2.nextInt();
            }
            inFileExam2.close();
        }
        else {
            return 'x';
        }

        if (grade >= 90) {
            letter = 'A';
        }
        else if (grade < 90 && grade >= 80) {
            letter = 'B';
        }
        else if (grade < 80 && grade >= 70) {
            letter = 'C';
        }
        else if (grade < 70 && grade >= 60) {
            letter = 'D';
        }
        else {
            letter = 'F';
        }

        return letter;
    }
}

The error occurs at the following line:

for (int i = 1; i <= count && inFileExam1.hasNextInt(); i++) {

Please help!!

Here is the main class:

import java.util.Scanner;
import java.io.*;

public class ExamAverages
{
public static void main(String[] args) throws IOException
{
Exam exam = new Exam();
System.out.println(exam.getExam1Avg());
System.out.println(exam.getExam2Avg());
System.out.println(exam.getLetterGrade("name", 1));
}

you are closing your scanner

inFileName.close();

and then trying to use it again without opening as like:

inFileName = new Scanner(..); 

EDIT1 It does not fail for me, but maybe i have missed some stuff (I still don't know how exactly you are willing to read these files, how they relate to each other)

public char getLetterGrade(String inputName, int examNum) {
    char letter;
    int count = 0;

    do {
        if (inFileName.hasNext()) {
            name = inFileName.nextLine();
        }
        count++;
    } while (inFileName.hasNext() && !name.equalsIgnoreCase(inputName));

    if (!name.equalsIgnoreCase(inputName)) {
        return 'x';
    }

    if (examNum == 1) {
        for (int i = 1; i <= count && inFileExam1.hasNextInt(); i++) {
            grade = inFileExam1.nextInt();
        }
        inFileExam1.close();
    } else if (examNum == 2) {
        for (int i = 1; i <= count && inFileExam2.hasNextInt(); i++) {
            grade = inFileExam2.nextInt();
        }
        inFileExam2.close();
    } else {
        return 'x';
    }

    if (grade >= 90) {
        letter = 'A';
    } else if (grade < 90 && grade >= 80) {
        letter = 'B';
    } else if (grade < 80 && grade >= 70) {
        letter = 'C';
    } else if (grade < 70 && grade >= 60) {
        letter = 'D';
    } else {
        letter = 'F';
    }

    return letter;
}

First of all, you're resetting grade every time you read a line, and you aren't doing anything with it, so that part of the code is useless.

But to answer your question:

According to the API, Scanner only returns an IllegalStateException after the object is closed using Scanner.close() or is somehow closed by the system.

Try moving your Scanner declaration for inFileExam1 next to where you are using it, like this:

if (examNum == 1) {
        inFileExam1 = new Scanner(exam1Data); // Add this
        for (int i = 1; i <= count && inFileExam1.hasNextInt(); i++) {
            grade = inFileExam1.nextInt();
        }
        inFileExam1.close();
    }
    else if (examNum == 2) {
        inFileExam2 = new Scanner(exam2Data); // And this
        for (int i = 1; i <= count && inFileExam2.hasNextInt(); i++) {
            grade = inFileExam2.nextInt();
        }
        inFileExam2.close();
    }
}

You don't include the code that has your main method, but I'm going to make an educated guess that you construct a new Exam object in it, and call getLetterGrade more than once. Since you open your Scanners in the constructor, and close them after reading, the second time you call getLetterGrade you will see an IllegalStateException .

If this psychic reading is inaccurate, can you please update your post with the contents of main(String[] args) ?

EDIT: After your latest edit I see that you call the getExam1Avg method before calling getLetterGrade . Since getExam1Avg calls close on your Scanner you get an IllegalStateException when calling the other method. You need to either instantiate a new scanner for each method call or otherwise reset the scanners after each method is complete.

Your error is in getAverageExam1Avg and the other one. Instead of closing your Scanner s in the getLetterGrade method, you should keep them open and add a close method like this:

public void close() {
    inFileName.close();
    inFileExam1.close();
    inFileExam2.close();
}

Make sure to add the proper exceptions into that code.

The reason it is failing now is because you haven't opened the Scanners. Un-comment the instantiations in the constructor.

If this doesn't work, I have no idea what will.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM