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

Java 从包含对象数组的二进制文件中读取特定索引,java,arrays,binaryfiles,Java,Arrays,Binaryfiles,我有一个在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

我有一个在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
对象,并且我知道它们的位置


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

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

如果您只需要知道元素的索引就可以直接访问该元素,那么必须构建一个真正的直接文件或索引文件。直接文件具有大小恒定的记录,例如
s
,因此记录
n
的偏移量为
n*s
。您可以通过Java类
RandomAccessFile
使用它。但不应直接对直接文件使用
readUTF
writeUTF
,因为以字节为单位的字符串长度取决于字符的数量和类型:

  • “\u0001”到“\u007F”范围内的所有字符都由一个字节表示
  • 空字符'\u0000'和'\u0080'到'\u07FF'范围内的字符由一对字节表示
  • 范围为“\u0800”到“\uFFFF”的字符值由三个字节表示
(参考号:)

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


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

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

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



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

    二进制文件格式是什么,如果没有这些信息,我怀疑您是否会得到答案。另外,在读取文件时,索引是什么意思?如果您使用的是Java序列化,则没有。您是否考虑过使用类似Sqlite的数据库?@nneonneo这是一个简单的学校项目,而不是实际的项目application@RC. 它是使用
    FileOutputStream
    创建的。您应该发布创建该文件的代码,您可以使用
    FileOutputStream
    编写任何“格式”,因此它不是线索:)
    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;
        }
    
    
    
    }