Java - 如何使 ObjectInputStream 从文件中读取所有对象

Java - How to make ObjectInputStream read all objects from file

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Scanner;
public class FileDemo implements Serializable
{
    static ArrayList<FileDemo> list=new ArrayList<FileDemo>();

    public static void main(String[] args) throws Exception 
    {
        File file=new File("log.txt");
        if(!file.createNewFile() && file.length()!=0)
        {
            FileInputStream fis=new FileInputStream("log.txt");
            ObjectInputStream ois=new ObjectInputStream(fis);
            while(true)
            {
                try{
                    list.add((FileDemo)ois.readObject());                   
                }
                catch(EOFException e) {
                    break;
                }
                catch(Exception e) {
                    e.printStackTrace();
                    break;
                }
            }
            ois.close();
            fis.close();
        }
        Scanner scn=new Scanner(System.in);
        int x=0;
        while(x!=3)
        {
            System.out.println("MENU");
            System.out.println("Enter 1 to add new object to file");
            System.out.println("Enter 2 to display list size");
            System.out.println("Enter 3 to exit");
            System.out.print("Enter your choice: ");
            x=scn.nextInt();
            if(x==1)
            {
                FileDemo filedemo=new FileDemo();
                list.add(filedemo);
                FileOutputStream fos=new FileOutputStream("log.txt",true);
                ObjectOutputStream oos=new ObjectOutputStream(fos);
                oos.writeObject(filedemo);
                oos.close();
                fos.close();
                System.out.println("Object Created");
            }
            else if(x==2)
                {
                    System.out.println(list.size());
                }
            else if(x==3)
                break;
            else
                System.out.println("Invaild choice");
        }
    }
}

你好, 在此程序中,每次用户在菜单中输入选项 1 时,都会创建一个 class 的新对象,将其保存到列表并保存到文件中。当我尝试在下一次执行程序时从文件中读取对象时,它只从文件中读取第一个对象,而在下一次 readObject() 调用时它会引发异常,如下所示:

java.io.StreamCorruptedException: invalid type code: AC
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at FileDemo.main(FileDemo.java:25)

我想知道如何读取文件中存储的所有对象并将它们添加到列表中。

谢谢, 克莱门特

ObjectOutputStream 被设计为只写入一次流。它不是为附加而设计的。最简单的解决方案是创建一个 List 并将该列表写入文件。另一种方法是创建自己的协议来包装对象输出流,尽管这可能更复杂。

简而言之,如果您想添加一个项目,您需要阅读那里的内容,将项目添加到列表和 replace/overwrite 文件。

顺便说一句,.txt 文件应该是文本文件,但是,对象流是二进制文件,因此您应该使用不同的扩展名。

您可以这样写,以明确区分处理用户输入的代码和存储用户数据的数据结构

import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class FileDemo implements Serializable {
    static class FileList implements Serializable {
        List<FileData> list = new ArrayList<>();
    }

    static class FileData implements Serializable { }

    public static void main(String[] args) throws IOException {
        File file = new File("log.data");
        FileList list = new FileList();
        if (file.exists()) {
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
                list = (FileList) ois.readObject();
            }
        }
        Scanner scn = new Scanner(System.in);
        while (true) {
            System.out.print("MENU\n" +
                    "Enter 1 to add new object to file\n" +
                    "Enter 2 to display list size\n" +
                    "Enter 3 to exit\n" +
                    "Enter your choice: ");
            int option = scn.nextInt();
            switch (option) {
                case 1:
                    list.list.add(new FileData());
                    File tmp = new File("log.data.tmp");
                    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(tmp))) {
                        oos.writeObject(list);
                    }
                    Files.move(tmp.toPath(), file.toPath(), REPLACE_EXISTING);
                    System.out.println("Object Added");
                    break;
                case 2:
                    System.out.println(list.list.size());
                    break;
                case 3:
                    return;
                default:
                    System.out.println("Invalid choice");
                    break;
            }
        }
    }
}

check this question

此外,您应该检查如何处理 java 中的资源,例如here.

如果您想在 .txt 文件中逐个对象保存,可以使用 JSON 解析器(例如 jackson