Java反序列化为什么报错?请帮我看看

img


package com.a27序列化;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class a01序列化 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        对象序列化流();
        对象反序列化流();
    }
    public static void 对象序列化流() throws IOException, ClassNotFoundException {
        Student stu = new Student(1001,"方光曦","男","大三");
        Student stu1 = new Student(1002,"罗明星","女","大三");
        List<Student> a = new ArrayList<>();
        a.add(stu);
        a.add(stu1);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("stu.txt",true));
        //将对象序列化到文件
        oos.writeObject(stu);
        oos.close();
    }
    public static void 对象反序列化流() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("stu.txt"));
            Object obj=null;
            while ((obj=ois.readObject())!=null){
                Student stu = (Student) obj;
                System.out.println(stu.getId()+","+stu.getName()+","+stu.getGender()+","+stu.getGrade());
            }} catch (EOFException e) {
        }
        catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

package com.a27序列化;

import java.io.Serializable;

public class Student implements Serializable {
    private int id;
    private String name;
    private String gender;
    private String grade;

    public Student(int id, String name, String gender, String grade) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.grade = grade;
    }

    public Student() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", grade='" + grade + '\'' +
                '}';
    }
}


img

https://blog.csdn.net/xcwll_sina/article/details/39370443


while ((obj=ois.readObject())!=null){
                Student stu = (Student) obj;
                System.out.println(stu.getId()+","+stu.getName()+","+stu.getGender()+","+stu.getGrade());
            }

报错是因为这个while循环有问题,因为你只write了一个对象到文件,当你read第二次的时候就会抛异常。
你只write一个对象,读取的时候也不需要while循环,直接


obj=ois.readObject()

即可。

知道错误原因,你就可以根据需要修改代码了。

如有帮助,请采纳,十分感谢!

1.在一个文件都有一个文件的头部和文件体。由于对多次使用FileOutputStream(文件名,true)构建的ObjectOutputStream对象向同一个文件写数据,在每次些数据的时候他都会向这个文件末尾先写入header在写入你要写的对象数据导致的。
2.解决办法:如图
写类:
public class ObjectAppendOutputStream extends ObjectOutputStream {
public ObjectAppendOutputStream() throws IOException {
super();
}

public ObjectAppendOutputStream(OutputStream out) throws IOException {
    super(out);
}

@Override
protected void writeStreamHeader() throws IOException {
    return;
}

}

然后改你的写入操作为
File file = new File("stu.txt");
if (file.exists() == false) {
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file, true);
if (file.length() < 1) {
oos = new ObjectOutputStream(fos);
} else {
oos = new ObjectAppendOutputStream(fos);
}

不需要循环

题主这个问题,并不是写一个然后循环读的问题。就算写一个,用循环读一样可以读出来,不会报错。出现报错是因为第二次执行向文件追加内容,再读就出现了问题。如果想要不报错,这里改为false就好

img

1)运行结果:

img

2)主要修改:

img

3)主要原理:
操作系统层面有写延迟,读文件时还没来得急写确认,所以报错AC (acknowledge的意思),
头写尾巴读,就没问题

img

4)调测不易,望采纳

5)代码在这里:


package com.askdebug.csdn.service.impl;

import com.askdebug.csdn.modal.Student;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
 
public class a01序列化 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        对象序列化流();
        对象反序列化流();
    }

    public static void 对象序列化流() throws IOException, ClassNotFoundException {
        Student stu = new Student(1001,"方光曦","男","大三");
        Student stu1 = new Student(1002,"罗明星","女","大三");
        List<Student> a = new ArrayList<>();
        a.add(stu);
        a.add(stu1);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("stu.txt",false));
        //将对象序列化到文件
        oos.writeObject(stu);
        oos.writeObject(stu1);
        oos.close();
    }
    public static void 对象反序列化流() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("stu.txt"));
            Object obj=null;
            while ((obj=ois.readObject())!=null){
                Student stu = (Student) obj;
                System.out.println(stu.getId()+","+stu.getName()+","+stu.getGender()+","+stu.getGrade());
            }} catch (EOFException e) {
        }
        catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


package com.askdebug.csdn.modal;

import java.io.Serializable;

/**
 * @author pcj
 * @date 2022/4/8
 * @note
 */
public class Student implements Serializable {
    private int id;
    private String name;
    private String gender;
    private String grade;

    public Student(int id, String name, String gender, String grade) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.grade = grade;
    }

    public Student() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", grade='" + grade + '\'' +
                '}';
    }
}

报错原因:
因为你写文件是可以拼接的,而你的输出流是对象,对象在一次输出的时候回写一个输出流的头,里面包含类的信息,就你这个代码里面,输出文件会有输出的类是Student类型,当你关闭输出流,再次打开文件往里写的时候,这个输出流的头会再写一遍,这就导致读的时候,只读一次类型信息,然后认为之后的就都是该类型的信息,当再次读到这个类型信息的时候就会无法识别,例子如下:
输出的文件
第一次关闭输出流的时候文件变成
头信息:这是一个Student类的输出文件 数据:1001,方光曦,男,大三;1002,罗明星,女,大三;
这个时候你读去信息是没有问题的
当你再次运行相同文件的时候,输出文件就变成下面这样了
头信息:这是一个Student类的输出文件 数据:1001,方光曦,男,大三;1002,罗明星,女,大三;头信息:这是一个Student类的输出文件 数据:1001,方光曦,男,大三;1002,罗明星,女,大三;
这个时候你会看到,有连个头信息,你再去读取,当读到头信息的时候,你就无法解析了。
解决方法:
你需要自己在写一个类,该类主要的作用就是,当判断文件中已经有信息的时候,不再写入头信息。
代码如下:

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class a01序列化 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        对象序列化流();
        对象反序列化流();
    }

    public static void 对象序列化流() throws IOException, ClassNotFoundException {
        Student stu = new Student(1001,"方光曦","男","大三");
        Student stu1 = new Student(1002,"罗明星","女","大三");
        List<Student> a = new ArrayList<>();
        a.add(stu);
        a.add(stu1);

        File file = new File("stu.txt");

        ObjectOutputStream oos = null;
        if(file.length()>1){
            oos = new AppendObjectOutputStream(new FileOutputStream(file, true));
        } else {
            oos = new ObjectOutputStream(new FileOutputStream(file, true));
        }

        //将对象序列化到文件
        for(Student student:a){
            oos.writeObject(student);
        }
        oos.close();

    }

    public static void 对象反序列化流() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("stu.txt"));
            Object obj=null;
            while ((obj=ois.readObject())!=null){
                Student stu = (Student) obj;
                System.out.println(stu.getId()+","+stu.getName()+","+stu.getGender()+","+stu.getGrade());
            }} catch (EOFException e) {
        }
        catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * 可拼接的对象输出流
 */
class AppendObjectOutputStream extends ObjectOutputStream{

    public AppendObjectOutputStream(OutputStream out) throws IOException {
        super(out);
    }

    @Override
    protected void writeStreamHeader() throws IOException {
        return;
    }
}

Student类不变

应该是写序列化文件多次造成的, 建议楼主别整些中文,随便一个单词都好,中文可读性太差了

中文方法名?这是用的什么编程语言?

读取的时候也不需要while循环

代码改成如下试试:望采纳

img

public class a01序列化{

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        对象序列化流();
        对象反序列化流();
    }

    public static void 对象序列化流() throws IOException, ClassNotFoundException {
        ObjectOutputStream out = null;
        String path = "d://test.txt";
        Student stu = new Student(1001,"方光曦","男","大三");
        Student stu1 = new Student(1002,"罗明星","女","大三");
        List<Student> a = new ArrayList<>();
        a.add(stu);
        a.add(stu1);

        try {      //判断文件大小并调用不同的方法
            File file = new File(path);
            FileOutputStream fos = new FileOutputStream(file, true);
            if(file.length()<1){
                out = new ObjectOutputStream(fos);
            }else{
                out = new MyObjectOutputStream(fos);
            }
            //判断文件大小并调用不同的方法
            for (int i = 0; i < a.size(); i++) {
                out.writeObject(a.get(i));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void 对象反序列化流() {
        String path = "d://test.txt";
        ObjectInputStream in = null;
        try {
            in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
            while (true) {
                Student s = (Student) in.readObject();
                System.out.println(s.getId()+","+s.getName()+","+s.getGender()+","+s.getGrade());
            }
        } catch (EOFException e) {

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();   
            }
        }
    }
}
public class MyObjectOutputStream extends ObjectOutputStream {

    protected MyObjectOutputStream() throws IOException, SecurityException {
        super();
    }

    @Override
    protected void writeStreamHeader() throws IOException {

    }

    public MyObjectOutputStream(OutputStream o) throws IOException{
        super(o);
    }
}