简体   繁体   中英

JAVA- Read .txt file with mix of strings & integers, store strings in an array and integers in a 2D array

I have a text file with student's names on one line, followed by 15 grades (each separated by 2 spaces & with a single space at the beginning of the line) on the next line.

Example:

    John, Elton
      89  97  91  94  82  96  98  67  69  97  87  90  100  80  92
    Johnson, Kay
      96  68  71  70  90  79  69  63  88  75  61  77  100  80  88

    (More data...)


I need to read the line containing the student name and store the value in a String array, then read the following line of grades, storing the values in 2D Integer array. On each line of integers, the first 10 values are to be considered assignment grades while the last 5 values are exam grades (To be used later when computing student averages). My program crashes due to an "Input Mismatch Exception" when it attempts to read the line of integers after the first student name. Here's my code so far:

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

public class Grades
{   
    // Declare constants for array lengths
    private static final int ROWS = 25;
    private static final int COLS = 15;

public static void main(String[] args) throws IOException
{
    // Create new two dimensional integer array to hold students assignment & exam grades
    int[][] grades = new int[ROWS][COLS];

    // Create new string array to hold student names
    String[] students = new String[ROWS];

    // Total number of students
    int numStudents;

    // Display your name
    System.out.println( "YOUR NAME" );

    // Fill the arrays
    numStudents = fillArray( grades, students );

    // Display the data that was just read in
    display(grades, students, numStudents);

}

 // The fillArray method opens & reads student name & grade data from a text file
private static int fillArray(int[][] sGrades, String[] sNames) throws IOException
{
    // Students counter
    int students = 0;   

    // Create the file
    File studentGrades = new File("Grades.txt");

    // Check that the file exists
    if (!studentGrades.exists())
    {
        // Display error message and exit the program
        System.out.println(studentGrades + " not found. Aborting.");
        System.exit(0);
    }

    // Create scanner object to read from the file
    Scanner gradeFile = new Scanner(studentGrades);

    // Read data until the end of the file is reached or the array is full
    while (gradeFile.hasNext() && students < sNames.length)
    {
        // Begin filling the array of student names starting with the first element
        for ( int i = 0; i < ROWS; i++ )
        {
            // Store the students name into the array's current index
            sNames[i] = gradeFile.nextLine();

            // Increment the number of students
            students++;

            // Begin filling in the array of grades starting with the first element

/*************   ERROR OCCURS HERE   ********************/
            for ( int j = 0; j < COLS; j++ )

                // Store the grade into the array's current index
                sGrades[i][j] = gradeFile.nextInt();
/**************                       *******************/
        }
    }
    // Close the file
    gradeFile.close();
    // Return the total number of students
    return students;
}
    // The display method prints Each student's name, 10 assignment 
    // grades and 5 exam grades
    // to the screen, separating each student by a blank line.
total number of students
private static void display(int[][] gradeArray, String [] studentArray, int totalStudents)
{
    //
    for ( int i = 0; i < totalStudents; i++)
    {
        System.out.println();
        //
        System.out.print("STUDENT:     " + studentArray[i]);

        System.out.print("\nASSIGNMENTS: ");
        //
        for ( int j = 0; j < 10; j++)
            //
            System.out.print(gradeArray[i][j] + " ");

        //
        System.out.print("\nEXAMS:       ");

        //
        for ( int k = 10; k < COLS; k++)
            //
            System.out.print(gradeArray[i][k] + " ");
        System.out.println();
    }

The output from the 'display' method should look like this:

    YOUR NAME

    STUDENT:     John, Elton
    ASSIGNMENTS: 89 97 91 94 82 96 98 67 69 97
    EXAMS:       87 90 100 80 92

    STUDENT:     Johnson, Kay
    ASSIGNMENTS: 96 68 71 70 90 79 69 63 88 75
    EXAMS:       61 77 100 80 88   

    (More output...)

Since the program crashes before I can see any output, I removed the following line of code that is trying to read the next Integer to see what is happening.

    for ( int j = 0; j < COLS; j++ )
        sGrades[i][j] = gradeFile.nextInt();

As I expected, each line of the file is read as a string and the value is stored in the array of student names resulting in output like this:

    STUDENT:     John, Elton
    ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 0
    EXAMS:       0 0 0 0 0

    STUDENT:     89 97 91 94 82 96 98 67 69 97 87 90 100 80 92
    ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 0
    EXAMS:       0 0 0 0 0

    STUDENT:     Johnson, Kay
    ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 0
    EXAMS:       0 0 0 0 0

    STUDENT:     96 68 71 70 90 79 69 63 88 75 61 77 100 80 88
    ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 0
    EXAMS:       0 0 0 0 0

    (More output...)

My brain hurts trying to figure out where I'm going wrong. If I were to guess, I would think it has to do with the spaces separating each integer causing each line of grades to be interpreted as a String instead of an integer. Or is there something else I may have overlooked?

EDIT: I am limited to using more basic Java techniques for this program. I cannot use Array Lists, exception handling other than a throws clause in the method headers. File-handling is limited to using the File & Scanner classes. No BufferReader or StringReader or FileReader .

Use Integer.parseInt(gradeFile.next()) instead of gradeFile.nextInt()

It works like this:

/************* ERROR OCCURS HERE ********************/
for (int j = 0; j < COLS; j++) {

    // Store the grade into the array's current index
    sGrades[i][j] = Integer.parseInt(gradeFile.next());
    /**************                       *******************/
}

if (gradeFile.hasNext())
    gradeFile.nextLine();

Surround your filling with try and catch statements as follow:

         try{
            sNames[i] = gradeFile.nextLine();
            }catch(Exception NoSuchElementException){   
            }

And write the for loop which generates the error like that :

                for ( int j = 0; j < COLS; j++ ){
                try{
                    sGrades[i][j]=gradeFile.nextInt() ;
                }catch(Exception NoSuchElementException){

                }


            }
            try{
                gradeFile.nextLine();
            }catch(Exception NoSuchElementException){

            }

The last gradeFile.nextLine() was missing after your for loop(that adds integers), I added it with a try and catch statement Tell me if it works :)

Well I've written an application to do exactly what you want.

Here it is:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {

    //Aka rows
    private static final int NO_STUDENTS = 25;
    //Grades per student. Aka columns.
    private static final int NO_GRADES = 15;

    //Names of all the students
    private final String[] STUDENTS = new String[NO_STUDENTS];

    //The students grades
    private final int[][] GRADES = new int[NO_STUDENTS][NO_GRADES];

    /**
     * Runs the application
     */
    public Main() {
        try {
            //Writes to the arrays from the text file
            parseReults("Results.txt");
            //Prints the results in the format
            printResults();
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Parses the students names and grades from a text file and writes them to
     * the arrays.
     *
     * @param resultsFile
     */
    private void parseReults(String resultsFile) throws IOException {
        BufferedReader reader = new BufferedReader(
                new StringReader(getTextFileContents(resultsFile)));

        int lineNo = 0;
        int studentNo = 0;
        int gradeNo = 0;
        String line;

        //Reads over every line in the file
        while ((line = reader.readLine()) != null) {
            //Is the line number odd, if so read students name else read
            //the grades
            if (lineNo % 2 == 0) {
                STUDENTS[studentNo] = line;
                studentNo++;
            } else {
                GRADES[gradeNo] = getGrades(line);
                gradeNo++;
            }

            lineNo++;
        }
    }

    /**
     * Prints the results from the arrays.
     */
    private void printResults() {
        System.out.println("YOUR NAME\n");

        for (int i = 0; i < STUDENTS.length; i++) {
            System.out.println("STUDENT: " + STUDENTS[i]);

            String assignments = "";

            for (int j = 0; j < 9; j++) {
                assignments += GRADES[i][j] + " ";
            }

            System.out.println("ASSIGNMENTS: " + assignments);

            String exams = "";

            for (int k = 9; k < 15; k++) {
                exams += GRADES[i][k] + " ";
            }

            System.out.println("EXAMS: " + exams);
            System.out.println("");
        }
    }

    public static void main(String[] args) throws IOException {
        Main m = new Main();
    }

    /**
     * Parses all the students grades from one line of text into an integer
     * array containing all the grades.
     * 
     * @param gradesLine
     * @return 
     */
    private static int[] getGrades(String gradesLine) {
        try {
            int[] grades = new int[NO_GRADES];

            StringReader reader = new StringReader(gradesLine);
            reader.read();//Get rid of the first space

            for (int i = 0; i < NO_GRADES; i++) {
                String grade = "";
                char letter;

                while ((letter = (char) reader.read()) != ' ') {
                    if (letter == '\n' || letter == (char) 65535) {
                        break;
                    }
                    grade += letter;
                }

                reader.read();//Get red of the second space
                grades[i] = Integer.parseInt(grade);
            }

            return grades;
        } catch (IOException ex) {
            //Isn't happening
        }

        return null;//Won't happen
    }

    /**
     * Reads an entire text file.
     *
     * @param fileName the name of the file
     * @return the file contents
     */
    private static String getTextFileContents(String fileName)
            throws FileNotFoundException, IOException {
        String contents = "";

        try (BufferedReader reader = new BufferedReader(
                new FileReader(new File(fileName)))) {
            String line;
            while ((line = reader.readLine()) != null) {
                contents += line + "\n";
            }
        }

        return contents;
    }
}

This is the "Results.txt" file:

John, Elton
 89  97  91 94  82  96  98  67  69  97  87  90  100  80  92
Johnson, Kay
 96  68  71  70  90  79  69  63  88  75  61  77  100  80  88
Amanda, Grey
 35  15  44  88  95  84  85  45  15  95  11  46  98  100  88

And finally, this is the output:

YOUR NAME

STUDENT: John, Elton
ASSIGNMENTS: 89 97 91 4 82 96 98 67 69 
EXAMS: 97 87 90 100 80 92 

STUDENT: Johnson, Kay
ASSIGNMENTS: 96 68 71 70 90 79 69 63 88 
EXAMS: 75 61 77 100 80 88 

STUDENT: Amanda, Grey
ASSIGNMENTS: 35 15 44 88 95 84 85 45 15 
EXAMS: 95 11 46 98 100 88 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

STUDENT: null
ASSIGNMENTS: 0 0 0 0 0 0 0 0 0 
EXAMS: 0 0 0 0 0 0 

Now, for how it works:

From the main(String[]) method, it initializes a new instance of Main .

In the constructor of Main , The parseResults(String fileName) method is called which reads the file and parses the results. Then, the printResults() method is called, which, as you can guess by the name, prints the results.

The parseResults() method: This is where all the magic happens. It begins by reading the whole file and then iterating over it line by line. If the line number of the line it's reading is an even number, it will take the text from the line and append it to the next row of the STUDENTS array. If the line number is odd, it knows this line holds the grades of the last student, so it calls the getGrades() method which parses a line of grades into an integer array holding all the grades from the line of text, then it appends the grades integer array to the next row of the GRADES array.

Try out something like this

private static final int COLS = 15;

public static void computeScores() throws IOException {
    int totalStudents = 0, totalMarks = 0;
    String[] lines = new String(Files.readAllBytes(Paths.get("data.txt"))).split("[\\r\\n]+");
    String[] sNames = new String[lines.length / 2];
    int[][] grades = new int[lines.length / 2][COLS];
    if (lines.length > 0) {
        for (int i = 0; i < lines.length; i++) {
            if (i % 2 == 0) {
                sNames[totalStudents] = lines[i];
                totalStudents++;
            } else {
                String[] marks = lines[i].split("  ");
                for (int j = 0; j < marks.length; j++)
                    grades[totalMarks][j] = Integer.parseInt(marks[j].trim());
                totalMarks++;
            }
        }
    }
}

//go ahead and print out your values the usual way you've been doing it

    for (int i = 0; i < totalStudents; i++) {
        System.out.println();
        //
        System.out.print("STUDENT: " + sNames[i]);

        System.out.print("\nASSIGNMENTS: ");
        //
        for (int j = 0; j < 10; j++)
            //
            System.out.print(grades[i][j] + " ");

        //
        System.out.print("\nEXAMS: ");

        //
        for (int k = 10; k < COLS; k++)
            //
            System.out.print(grades[i][k] + " ");
        System.out.println();
    }

This should print just fine

Thanks for everyone's input. I figured out the problem was an unnecessary for loop to process student names. I modified my code in the fillArray() method to look like this:

private static int fillArray(int[][] sGrades, String[] sNames) throws IOException
{
    int students = 0;   // Students counter

    // Create the file
    File studentGrades = new File("Grades.txt");

    // Check that the file exists
    if (!studentGrades.exists())
    {
        // Display error message and exit the program
        System.out.println(studentGrades + " not found. Aborting.");
        System.exit(0);
    }
    // Create scanner object to read from the file
    Scanner gradeFile = new Scanner(studentGrades);

    // Read data until the end of the file is reached or array is full
    while (gradeFile.hasNext() && students < ROWS)
    {
        sNames[students] = gradeFile.nextLine();

        for ( int i = 0; i < COLS; i++ )
            sGrades[students][i] = gradeFile.nextInt();

        students++;
        gradeFile.nextLine();
    }

    // Close the file
    gradeFile.close();
    // Return the total number of students
    return students;
}

And voila!

    STUDENT:     John, Elton
    ASSIGNMENTS: 89 97 91 94 82 96 98 67 69 97 
    EXAMS:       87 90 100 80 92 

    STUDENT:     Johnson, Kay
    ASSIGNMENTS: 96 68 71 70 90 79 69 63 88 75 
    EXAMS:       61 77 100 80 88 

    STUDENT:     Liston, Ed
    ASSIGNMENTS: 78 98 98 85 96 96 64 60 81 61 
    EXAMS:       66 83 100 98 93 

    STUDENT:     Kelly, Michael
    ASSIGNMENTS: 72 64 76 76 86 100 69 87 76 79 
    EXAMS:       76 93 100 78 82 

    STUDENT:     Presley, Elvis
    ASSIGNMENTS: 92 94 100 50 82 79 72 75 78 85 
    EXAMS:       70 76 100 87 79 

    STUDENT:     Hughes, Meghan
    ASSIGNMENTS: 90 97 89 100 94 88 70 92 90 92 
    EXAMS:       91 84 100 94 71 

    STUDENT:     Madonna
    ASSIGNMENTS: 97 97 84 94 96 91 86 95 90 98 
    EXAMS:       93 91 100 98 96 

    STUDENT:     Pacino, Al
    ASSIGNMENTS: 73 71 77 70 89 100 82 0 90 77 
    EXAMS:       5 77 100 80 74 

    STUDENT:     Bush, George W.
    ASSIGNMENTS: 76 73 60 82 79 74 66 77 73 86 
    EXAMS:       70 78 100 77 90 

    STUDENT:     Burke, Maggie
    ASSIGNMENTS: 94 73 74 79 66 78 43 90 97 91 
    EXAMS:       87 79 100 67 90 

    STUDENT:     Diesel, Vin
    ASSIGNMENTS: 60 64 89 66 52 70 67 66 67 66 
    EXAMS:       55 73 100 75 45 

    STUDENT:     Spiderman
    ASSIGNMENTS: 89 75 91 99 91 80 100 98 91 78 
    EXAMS:       92 93 100 92 99 

    STUDENT:     Baggins, Bilbo
    ASSIGNMENTS: 82 81 55 89 71 74 35 68 86 96 
    EXAMS:       65 0 100 71 61 

    STUDENT:     Williams, Serena
    ASSIGNMENTS: 100 94 96 98 90 90 92 91 92 90 
    EXAMS:       88 94 100 82 92 

    STUDENT:     Baggins, Frodo
    ASSIGNMENTS: 68 78 80 73 83 74 74 67 39 81 
    EXAMS:       65 88 100 68 92 

    STUDENT:     Potter, Harry
    ASSIGNMENTS: 87 61 78 89 86 80 70 72 77 83 
    EXAMS:       65 93 100 86 67 

    STUDENT:     Cianci, Buddy
    ASSIGNMENTS: 98 70 60 91 67 81 89 64 70 77 
    EXAMS:       62 77 100 92 76 

    STUDENT:     Basilico, Anthony
    ASSIGNMENTS: 67 69 76 76 75 67 83 83 88 75 
    EXAMS:       63 63 100 82 100 

    STUDENT:     Clapton, Eric
    ASSIGNMENTS: 100 85 64 89 83 68 84 91 84 66 
    EXAMS:       81 84 100 100 95 

    STUDENT:     Lennon, John
    ASSIGNMENTS: 88 65 84 68 80 90 61 62 88 75 
    EXAMS:       74 75 100 80 76 

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