Conner K. McPhee Conner K. McPhee - 27 days ago 14
Java Question

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();
}
}

Answer

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();
}

If this method helped you, please upvote the answer and flag as answered :D

Comments