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

时间:2015-08-13 16:58:29

标签: java arrays binaryfiles

我有一个在Java程序中创建的二进制文件。二进制文件包含一个User对象数组。

它是这样创建的:

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类:

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对象,我知道它们的位置。

有没有办法读取只是我想读的索引,而不读取所有内容?

1 个答案:

答案 0 :(得分:2)

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

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

  • 范围内的所有字符&#39; \ u0001&#39;到&#39; \ u007F&#39;用单个字节表示
  • 空字符&#39; \ u0000&#39;以及范围内的字符&#39; \ u0080&#39;到&#39; \ u07FF&#39;由一对字节
  • 表示
  • 范围内的字符值&#39; \ u0800&#39;到&#39; \ uFFFF&#39;用三个字节表示

(参考:Javadoc for DataInput

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

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

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

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

    如果您发现上述内容过于复杂,请使用数据库。 Derby或H2可以用作嵌入式数据库,这将更加简单。