First of all i'm a beginner.(Please Excuse my mistakes) I'm trying to make a student information system. The 'Student' class inherits from the 'Person' class. In the methods inside the "StudentServices" class, data is written to the "student.bin" file. My goal is to show the object information in the file line by line on the screen.(With ObjectInputStream) But it's not working. I'm getting an exception.
Parent class named "Person". All classes are serialized.
public class Person implements Serializable{
private String name;
private String surname;
private long id;
private String gender;
public Person(String name, String surname, long id, String gender) {
this.name = name;
this.surname = surname;
this.id = id;
this.gender = gender;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Person{"
"name='" name '\''
", surname='" surname '\''
", id=" id
", gender='" gender '\''
'}';
}
}
Child class named "Student"
public class Student extends Person implements Serializable
private Department department;
private int number; //student number
private float graduationGrade;
public Student(String name, String surname, long id, String gender,
Department department, int number, float graduationGrade) {
super(name, surname, id, gender);
this.department = department;
this.number = number;
this.graduationGrade = graduationGrade;
}
public float getGraduationGrade() {
return graduationGrade;
}
public void setGraduationGrade(float graduationGrade) {
this.graduationGrade = graduationGrade;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public String toString() {
return "Student{"
"department=" department
", number=" number
", graduationGrade=" graduationGrade
"} " super.toString();
}
}
This is the Student İnterface;
public interface IStudent {
void list();
void update();
void delete();
void add();
void save(Student student);
}
Here is the Deparment class.
public class Department implements Serializable{
private String name; //department name
public Department() {
}
public Department(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Department{"
"name='" name '\''
'}';
}
}
Also i have StudentService class who implements IStudent interface. In this class; methods named add(), List(), Update(), Delete(), Save() have bodies.(delete() and update() are not written yet...)
public class StudentServices implements IStudent {
Scanner scanner = new Scanner(System.in);
@Override
public void list() {
try (ObjectInputStream ois = new ObjectInputStream((new
FileInputStream("src/DatabaseFile/Student.bin"))))
{
while (true) {
Student student = (Student) ois.readObject();
System.out.println(student);
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
@Override
public void add() {
Department department = new Department();
Student student = new Student();
System.out.println("Student Name : ");
student.setName(scanner.next());
System.out.println("Student SurName : ");
student.setSurname(scanner.next());
System.out.println("Student Number : ");
student.setNumber(scanner.nextInt());
System.out.println("Student Department : ");
department.setName(scanner.next());
student.setDepartment(department);
System.out.println("Student Gender : ");
student.setGender(scanner.next());
System.out.println("Student ID (TCKN) : ");
student.setId(scanner.nextLong());
System.out.println("Student Graduation Grade: ");
student.setGraduationGrade(scanner.nextFloat());
System.out.println(" ***** Press 5 To Save! *****");
System.out.println(" ***** Press 6 To Not Save! *****");
int choice = scanner.nextInt();
if (choice == 5) {
save(student);
} else {
System.out.println("** Your Actions Are Not Saved!**");
System.out.println("Exiting...");
MainTest.menu();
}
}
@Override
public void save(Student student) {
try (ObjectOutputStream oos =
new ObjectOutputStream((new
FileOutputStream("src/DatabaseFile/Student.bin"))))
{
oos.writeObject(student);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void delete() {
}
@Override
public void update() {
}
}
And I have a main class that only calls the menu;
public class MainTest {
public static void main(String[] args) {
System.out.println("\n----------- S C H O L L I N F O R M A T I O
N S Y S T E M ------------");
menu();
}
public static void menu() {
Scanner scanner = new Scanner(System.in);
StudentServices studentServices = new StudentServices();
TeacherServices teacherServices = new Teacher.TeacherServices();
outerloop:
do {
System.out.println("\nChoose Operation ;\n"
"For Student Operation Press \" S \" "
"\nFor Teacher Operations Press \" T \""
"\nFor Exit Press 6");
char operation = scanner.next().charAt(0);
switch (operation) {
//Student
case 's':
case 'S': {
System.out.println("1-List Student");
System.out.println("2-Add Student");
System.out.println("5-Save All");
System.out.println("3-Delete Student");
System.out.println("4-Update Student");
System.out.println("6-Exit");
System.out.print("\nChoice:");
int choice = scanner.nextInt();
switch (choice) {
case 1:
studentServices.list();
break;
case 2:
studentServices.add();
break;
case 3:
studentServices.delete();
break;
case 4:
studentServices.update();
break;
case 5:
System.out.println("You Haven't Added Any
Students Yet! Press 2 To Add Students...");
break;
case 6:
System.out.println("Exiting...");
break outerloop;
default:
System.out.println("You entered incorrectly,
please try again...");
break;
}
}
break;
case 'T':
case 't': {
System.out.println("1-List Teacher");
System.out.println("2-Add Teacher");
System.out.println("3-Delete Teacher");
System.out.println("4-Update Teacher");
System.out.println("5-Save All");
System.out.println("6-Exit");
System.out.println("Choice:");
int choice = scanner.nextInt();
switch (choice) {
case 1:
teacherServices.list();
break;
case 2:
teacherServices.add();
break;
case 3:
teacherServices.delete();
break;
case 4:
teacherServices.update();
break;
case 5:
System.out.println("You haven't added any
students yet! Press 2 to add students...");
break;
case 6:
System.out.println("Exiting...");
System.exit(0);
default:
System.out.println("You entered incorrectly,
please try again...");
break;
}
}
break;
case '6':
System.out.println("Exiting...");
System.exit(0);
default:
System.out.println("You entered incorrectly, please try again...");
break;
}
} while (true);
}
}
I am getting this exception;
java.io.EOFException
at java.base/java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:3159)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1640)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:495)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:453)
at Student.StudentServices.list(StudentServices.java:19)
at Main.MainTest.menu(MainTest.java:47)
at Main.MainTest.main(MainTest.java:14)*
CodePudding user response:
Rather than serializing and deserializing the Student
instances, convert the instance to a String
and write it to a text file. Add method(s) that can read the String
from the file and convert it into a Student
class. Below code demonstrates. Note that it uses regular expressions to parse the String
read from the text file that stores the Student
instances. You may need to modify the patterns to make them more suitable to your needs as it is not clear to me what characters are valid for the fields name
, surname
and gender
(all in class Person
) as well as name
in class Department
.
Class Person
no longer needs to implement interface java.io.Serializable
.
Class Department
no longer needs to implement interface java.io.Serializable
.
I only changed class Student
and class StudentServices
. Here is the code of those two classes. Note that I renamed the file but you can name it anything you like and place it in any directory that you like.
Class Student
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Student extends Person {
private Department department;
private int number; // student number
private float graduationGrade;
public Student() {
this(null, null, 0L, null, null, 0, 0.0f);
}
public Student(String name,
String surname,
long id,
String gender,
Department department,
int number,
float graduationGrade) {
super(name, surname, id, gender);
this.department = department;
this.number = number;
this.graduationGrade = graduationGrade;
}
public static Student fromString(String str) {
Department dept = getDepartmentFromString(str);
String gender = getGenderFromString(str);
float grade = getGraduationGradeFromString(str);
long id = getIdFromString(str);
String name = getNameFromString(str);
int number = getNumberFromString(str);
String surname = getSurnameFromString(str);
return new Student(name, surname, id, gender, dept, number, grade);
}
public static Department getDepartmentFromString(String str) {
Pattern pattern = Pattern.compile("department=Department\\{name='([a-zA-Z0-9] )'\\},");
Matcher matcher = pattern.matcher(str);
Department dept;
if (matcher.find()) {
dept = new Department(matcher.group(1));
}
else {
dept = null;
}
return dept;
}
public static String getGenderFromString(String str) {
Pattern pattern = Pattern.compile(", gender='([a-zA-Z] )'\\}");
Matcher matcher = pattern.matcher(str);
String gender;
if (matcher.find()) {
gender = matcher.group(1);
}
else {
gender = null;
}
return gender;
}
public static float getGraduationGradeFromString(String str) {
Pattern pattern = Pattern.compile(", graduationGrade=(\\d \\.\\d )\\} ");
Matcher matcher = pattern.matcher(str);
float grade;
if (matcher.find()) {
String temp = matcher.group(1);
grade = Float.parseFloat(temp);
}
else {
grade = 0.0f;
}
return grade;
}
public static long getIdFromString(String str) {
Pattern pattern = Pattern.compile(", id=(\\d ), ");
Matcher matcher = pattern.matcher(str);
long id;
if (matcher.find()) {
String temp = matcher.group(1);
id = Long.parseLong(temp);
}
else {
id = 0;
}
return id;
}
public static String getNameFromString(String str) {
Pattern pattern = Pattern.compile("\\} Person\\{name='([a-zA-Z] )', ");
Matcher matcher = pattern.matcher(str);
String name;
if (matcher.find()) {
name = matcher.group(1);
}
else {
name = null;
}
return name;
}
public static int getNumberFromString(String str) {
Pattern pattern = Pattern.compile("'\\}, number=(\\d ), ");
Matcher matcher = pattern.matcher(str);
int number;
if (matcher.find()) {
String temp = matcher.group(1);
number = Integer.parseInt(temp);
}
else {
number = 0;
}
return number;
}
public static String getSurnameFromString(String str) {
Pattern pattern = Pattern.compile("', surname='([a-zA-Z] )', ");
Matcher matcher = pattern.matcher(str);
String surname;
if (matcher.find()) {
surname = matcher.group(1);
}
else {
surname = null;
}
return surname;
}
public float getGraduationGrade() {
return graduationGrade;
}
public void setGraduationGrade(float graduationGrade) {
this.graduationGrade = graduationGrade;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public String toString() {
return "Student{" "department=" department ", number=" number ", graduationGrade=" graduationGrade
"} " super.toString();
}
}
Class StudentServices
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Scanner;
public class StudentServices implements IStudent {
Scanner scanner = new Scanner(System.in);
@Override
public void list() {
try (BufferedReader br = Files.newBufferedReader(Path.of("students.txt"))) {
String line = br.readLine();
while (line != null) {
Student student = Student.fromString(line);
System.out.println(student);
line = br.readLine();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void add() {
Department department = new Department();
Student student = new Student();
System.out.println("Student Name : ");
student.setName(scanner.next());
System.out.println("Student SurName : ");
student.setSurname(scanner.next());
System.out.println("Student Number : ");
student.setNumber(scanner.nextInt());
System.out.println("Student Department : ");
department.setName(scanner.next());
student.setDepartment(department);
System.out.println("Student Gender : ");
student.setGender(scanner.next());
System.out.println("Student ID (TCKN) : ");
student.setId(scanner.nextLong());
System.out.println("Student Graduation Grade: ");
student.setGraduationGrade(scanner.nextFloat());
System.out.println(" ***** Press 5 To Save! *****");
System.out.println(" ***** Press 6 To Not Save! *****");
int choice = scanner.nextInt();
if (choice == 5) {
save(student);
}
else {
System.out.println("** Your Actions Are Not Saved!**");
System.out.println("Exiting...");
MainTest.menu();
}
}
@Override
public void save(Student student) {
try (FileWriter fw = new FileWriter("students.txt", true);
PrintWriter pw = new PrintWriter(fw, true)) {
pw.println(student);
}
catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void delete() {
}
@Override
public void update() {
}
}
CodePudding user response:
Below, you will find an example of what the replies to your thread are suggesting that you do. You already catch IOException
s, so we can check if the IOException
is of type EOFException
. In the event we do have the expected EOFException, we can simply avoid printing the stack trace, as no true error has occurred here. You can still use while(true)
, so long as you are certain you will eventually hit the EOFException
.
@Override
public void list() {
try (ObjectInputStream ois = new ObjectInputStream((new
FileInputStream("src/DatabaseFile/Student.bin"))))
{
while (true) {
Student student = (Student) ois.readObject();
System.out.println(student);
}
} catch (IOException | ClassNotFoundException e) {
if(e instanceof EOFException){ //this is new to your code
//ignore
}else{
e.printStackTrace();
}
}
}
I tried to avoid modifying your code much, so that it is clear what has changed between the two.
For further reference on EOFException
:
https://docs.oracle.com/javase/8/docs/api/java/io/EOFException.html