Search code examples
javadatabaseutf-8binarybinaryfiles

EOFException Reading UTF from Binary file, Student Database


I am having a lot of trouble reading in binary values from my Student Database problem. After some tinkering I got the output to work correctly and in the format, I wanted i.e.( int id, String name, int age) however, I am having a lot of trouble loading the encoded binary data values from my file. According to the compiler, It reads all the way up until the UTF value, then I receive an EOFException.

Here is the problem I am attempting to complete:

First, after starting up the program, the user selects the option to either 1. Add a student to the database 2. Remove a student from the database 3. Print a specific student in the database 4. Print ALL students in the database

If they select, the user will add a Student obj to a vector of students. The student obj contains an ID(int), a Name(String), and an age(int).

Removing a student removes them from the vector based on the ID number the user inputs.

And options 3/4 print the student obj(s) to the screen themselves (NOT TO THE BINARY FILE)

After the user quits the program by inputting 5; the student obj's in the vector are written to a Binary file.

And when the program is re-run, it will load the student obj's back into the vector. (Remeber the file was WRITTEN AND LOADED FROM A BINARY FILE)

The problem I am having is that when the file "Student.data" (the file I am currently writing to) is being loaded it keeps throwing me an EOFException at line 198 when I try to read the Student's name.

I believe the problem could be when I write the code but I have modified the way I grab the name values and write them multiple times I still have not been able to load them properly.

Any suggestions on how to fix this problem?

Code:

//StudentDB.java
import java.util.Vector;
import java.io.*;
import java.util.Scanner;
class Student
{
    private int id;
    private String name;
    private int age;
    //Desc: Initializes the student to id=0, name="none", and age=0
    public Student()
    {
        this.id=0;
        this.name="none";
        this.age=0;
    }
    //Desc: Initializes the student to id=i, name=n, age=a
    public Student(int I, String n, int a)
    {
        this.id=I;
        this.name=n;
        this.age=a;
    }
    //Desc: Sets the current id to s
    public void setID(int s)
    {
        this.id=s;
    }
    //Return: The current ID value
    public int getID()
    {
        return this.id;
    }
    //Desc: sets the current name of the student to s
    public void setName(String s)
    {
        this.name=s;
    }
    //Return: The current name of the student
    public String getName()
    {
        return this.name;
    }
    //Desc: sets the current age of the obj to a
    public void setAge(int a)
    {
        this.age=a;
    }
    //Return: The students current age
    public int getAge()
    {
        return this.age;
    }
    //Return: True if id of this student equals id of obj, false otherwise
    public boolean equals(Object obj)
    {
        Student stu= (Student)obj;
        if(this.id==stu.id) return true;
        else return false;
    }
    //Desc: Compares two students based on their ID to determine if they're
    // the same
    //Return: 1  if the current Student's ID is greater than stu
    //      0 if the students ID's are the same
    //      -1 if Student stu's ID is larger
    public int compareTo(Student stu)
    {
        if(this.id> stu.id) return 1;

        else if(this.id==stu.id) return 0;

        else return -1;

    }
    //Return: id+"Name"+age
    public String toString()
    {
            return (this.getID()+ " "+this.getName()+" "+this.getAge());
    }
}
public class StudentDB
{
    private static Scanner keyboard=new Scanner(System.in);
    //Desc: Maintains a database of Student Records. The database is stored in
    // a binary file called "Student.data"
    //Input: User enters commands from keyboard to manipulate database
    //Output: Database updated as directed by user.
    public static void main(String[]args) throws IOException
    {
        Vector<Student> v= new Vector<Student>();
        File s= new File("Student.data");
        if(s.exists()) loadStudent(v);
        int choice=5;
        do
        {
            System.out.println("\t1. Add a Student Record");
            System.out.println("\t2. Remove a Student Record");
            System.out.println("\t3. Print a Student Record");
            System.out.println("\t4. Print all Student Records");
            System.out.println("\t5. Quit");
            choice= keyboard.nextInt();
            keyboard.nextLine();
            switch(choice)
            {
                case 1: addStudent(v); break;
                case 2: removeStudent(v); break;
                case 3: printStudent(v); break;
                case 4: printAllStudent(v); break;
                default: break;
            }
        } while(choice!=5);
        storeStudent(v);
    }
    //Input: user enters an integer(id), a string(name), an integer(age) from
    //the keyboard all on seperate lines
    //Post: The input record added to v if id does not exist
    //Output: various prompts as well as "Student Added" or "Add failed:
    // Student already exists" printed on the screen accordingly
    public static void addStudent(Vector<Student> v)
    {
        Student stu= new Student();

        System.out.print("Please enter a Student ID:");
        stu.setID(keyboard.nextInt());
        keyboard.nextLine();

        System.out.print("Please enter a Student Name:");
        stu.setName(keyboard.nextLine());

        System.out.print("Please enter a Student Age:");
        stu.setAge(keyboard.nextInt());
        keyboard.nextLine();

        int index= v.indexOf(stu);
        if(index==-1)
        {
            v.add(stu);
            System.out.println("Student Added");
        }
        else System.out.println("Add failed: Student already exists");

    }
    //Input: user enters an integer(id) from the Keyboard
    //Post: The records in v whose id field matches the input removed from v
    //Output: various prompts as well as "Student removed" or "Remove failed:
    // Student does not exsist" printed on the screen accordingly
    public static void removeStudent(Vector<Student>v)
    {
        System.out.print("Student ID:");
        int id= keyboard.nextInt();
        Student stu= new Student(id,"",99);
        if(v.remove(stu))   System.out.println("Student Removed");
        else System.out.println("Remove Failed");
    }
    //Input: user enters an integer(id) from the Keyboard
    //Output: various prompts as well as the record in v whose id field 
    // matches the input printed on the screen or "Print failed: Student
    // does not exsist" printed on the screen accordingly
    public static void printStudent(Vector<Student>v)
    {
        System.out.print("Student ID:");
        int id= keyboard.nextInt();
        Student stu= new Student(id,"",99);
        int index=v.indexOf(stu);
        if(index!=-1)
        {
            System.out.println(v.get(index).toString());
        }
        else System.out.println("Print failed: Student does not exsist!");
    }
    //Output: All records in v printed on the screen 
    public static void printAllStudent(Vector<Student>v)
    {
        Student stu=new Student();
        for(int i=0; i<v.size();++i)
        {
            stu=v.get(i);
            System.out.println(stu);
        }

    }
    //Input: Binary file Student.data must exist and contains student records
    //Post: All records in Student.data loaded into vector v.
    public static void loadStudent(Vector<Student>v)throws IOException
    {
        Student stu;
        int c;
        DataInputStream f= new DataInputStream(
                new FileInputStream("Student.data"));
       try {
           while(true)
           {
               stu=new Student();
               int id=f.readInt();
               stu.setID(id);
               String name= f.readUTF();
               stu.setName(name);
               int age= f.readInt();
               stu.setAge(age);
               v.add(stu);
           }
       }
       catch(EOFException e)
       {
           System.out.println("Error!: End of File Exception");
           f.close();
       }
       catch(IOException e)
       {
           System.out.println("Error Reading File");
           f.close();
           System.exit(1);
       }
        f.close();
    }
    //Output: All records in v written to binary file Student.data
    public static void storeStudent(Vector<Student>v) throws IOException
    {
        Student stu= new Student();
        DataOutputStream s= new DataOutputStream(
                new FileOutputStream("Student.data"));
        for(int i=0; i<v.size(); ++i)
        {
            stu=v.get(i);
            s.writeInt(stu.getID());
            s.writeUTF(stu.getName());
            s.writeInt(stu.getAge());
        }
        s.close();
    }
}

Solution

  • Two reason's it's breaking.

    1. You have an infinite read
    2. You are appending every student to the same line

    make the following changes

    loadStudent Change white(true) to while(f.available() > 0) and add f.readChar(); at the end.

    public static void loadStudent(Vector<Student>v)throws IOException
    {
        Student stu;
        int c;
        DataInputStream f= new DataInputStream(
                new FileInputStream("Student.data"));
       try {
           // CHANGE HERE IS IMPORTANT
           while(f.available() > 0)
           {
               stu=new Student();
               int id=f.readInt();
    
               stu.setID(id);
               String name= f.readUTF();
               stu.setName(name);
               int age= f.readInt();
               stu.setAge(age);
               v.add(stu);
               // This read char is important since it's one user per line.
               f.readChar();
           }
       }
       catch(EOFException e)
       {
           System.out.println("Error!: End of File Exception");
           f.close();
       }
       catch(IOException e)
       {
           System.out.println("Error Reading File");
           f.close();
           System.exit(1);
       }
        f.close();
    }
    

    storeStudent When saving students, add a new line character at the end. s.writeChar('\n');

    public static void storeStudent(Vector<Student>v) throws IOException
    {
        Student stu= new Student();
        DataOutputStream s= new DataOutputStream(
                new FileOutputStream("Student.data"));
        for(int i=0; i<v.size(); ++i)
        {
            stu=v.get(i);
            s.writeInt(stu.getID());
            s.writeUTF(stu.getName());
            s.writeInt(stu.getAge());
            // One user per line
            s.writeChar('\n');
            }
        s.close();
    }