从包含对象数组的二进制文件中读取特定索引

Read a specific index from a binary file containing an array of objects

我有一个二进制文件,是在 Java 程序中创建的。二进制文件包含一组用户对象。

它是这样创建的:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {
    public static void main(String[] args) {

        User[] arrayOfUsers = new User[50];
        for (int i = 0; i < 50; i++){
            arrayOfUsers[i] = new User("Mr. ", i + "owitz");
        }

        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users.dat"));
            oos.writeObject(arrayOfUsers);
            oos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

这是User class:

import java.io.Serializable;

public class User implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    private String firstname;
    private String lastname;
    public User(String firstname, String lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastname() {
        return lastname;
    }
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }



}

到目前为止,我只知道如何一次读取整个数组。但是,我通常只需要从数组中检索一两个 User 对象,并且我知道它们的位置。

有什么方法可以只阅读我想阅读的索引,而无需阅读所有内容?

您不是在构建直接文件,而只是一个顺序文件,它恰好包含 Java ArrayList 的可序列化版本。所以你只能读回内存中的整个 ArrayList 再次处理它并访问单个元素。

如果你希望能够直接访问一个只知道其索引的元素,你将不得不构建一个真正的直接文件或索引文件。直接文件具有固定大小的记录,比如 s,因此记录 n 的偏移量是 n * s。您可以通过 Java class RandomAccessFile 使用它。但是你不应该直接使用 readUTFwriteUTF 作为直接文件,因为字符串的字节长度取决于字符的数量和类型:

  • '\u0001' 到 '\u007F' 范围内的所有字符都由一个字节表示
  • 空字符'\u0000'和'\u0080'到'\u07FF'范围内的字符由一对字节表示
  • '\u0800' 到 '\uFFFF' 范围内的字符值由三个字节表示

(参考:Javadoc for DataInput

所以你最好明确地将它们转换为 byte[]String.getBytes() 至少现在更容易控制大小,并手动写入大小然后是字节。或者,您可以跳过转换为字节,在 Char 中写入大小,然后写入各个字符。


如果您几乎从不修改值或添加值,则可以使用索引文件。基础是首先有一个包含记录偏移量的数组。这允许记录不具有相同的大小。一个可能的设计是:

  1. 偏移量数组中的条目数 (int n)
  2. n int 用于偏移量
  3. 数据

要写入文件,您需要计算数据区域的开始:(1 + n) * 4,并创建一个用于存储偏移量的 int 数组。然后你将 n+1 0 写入要正确定位的文件,并写入你的字符串,始终保存第一条记录的写入位置。最后你定位回0,写入记录数和偏移量。

要读取,只需读取记录数和偏移量即可。然后您可以浏览该文件。这主要用于未知和可变大小的大记录


如果你觉得上面的太复杂了,就用数据库吧。 Derby或者H2都可以作为嵌入式数据库使用,这样会简单很多。