从包含对象数组的二进制文件中读取特定索引
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
使用它。但是你不应该直接使用 readUTF
或 writeUTF
作为直接文件,因为字符串的字节长度取决于字符的数量和类型:
- '\u0001' 到 '\u007F' 范围内的所有字符都由一个字节表示
- 空字符'\u0000'和'\u0080'到'\u07FF'范围内的字符由一对字节表示
- '\u0800' 到 '\uFFFF' 范围内的字符值由三个字节表示
所以你最好明确地将它们转换为 byte[]
和 String.getBytes()
至少现在更容易控制大小,并手动写入大小然后是字节。或者,您可以跳过转换为字节,在 Char
中写入大小,然后写入各个字符。
如果您几乎从不修改值或添加值,则可以使用索引文件。基础是首先有一个包含记录偏移量的数组。这允许记录不具有相同的大小。一个可能的设计是:
- 偏移量数组中的条目数 (
int n
)
- n int 用于偏移量
- 数据
要写入文件,您需要计算数据区域的开始:(1 + n) * 4,并创建一个用于存储偏移量的 int 数组。然后你将 n+1 0
写入要正确定位的文件,并写入你的字符串,始终保存第一条记录的写入位置。最后你定位回0,写入记录数和偏移量。
要读取,只需读取记录数和偏移量即可。然后您可以浏览该文件。这主要用于未知和可变大小的大记录
如果你觉得上面的太复杂了,就用数据库吧。 Derby或者H2都可以作为嵌入式数据库使用,这样会简单很多。
我有一个二进制文件,是在 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
使用它。但是你不应该直接使用 readUTF
或 writeUTF
作为直接文件,因为字符串的字节长度取决于字符的数量和类型:
- '\u0001' 到 '\u007F' 范围内的所有字符都由一个字节表示
- 空字符'\u0000'和'\u0080'到'\u07FF'范围内的字符由一对字节表示
- '\u0800' 到 '\uFFFF' 范围内的字符值由三个字节表示
所以你最好明确地将它们转换为 byte[]
和 String.getBytes()
至少现在更容易控制大小,并手动写入大小然后是字节。或者,您可以跳过转换为字节,在 Char
中写入大小,然后写入各个字符。
如果您几乎从不修改值或添加值,则可以使用索引文件。基础是首先有一个包含记录偏移量的数组。这允许记录不具有相同的大小。一个可能的设计是:
- 偏移量数组中的条目数 (
int n
) - n int 用于偏移量
- 数据
要写入文件,您需要计算数据区域的开始:(1 + n) * 4,并创建一个用于存储偏移量的 int 数组。然后你将 n+1 0
写入要正确定位的文件,并写入你的字符串,始终保存第一条记录的写入位置。最后你定位回0,写入记录数和偏移量。
要读取,只需读取记录数和偏移量即可。然后您可以浏览该文件。这主要用于未知和可变大小的大记录
如果你觉得上面的太复杂了,就用数据库吧。 Derby或者H2都可以作为嵌入式数据库使用,这样会简单很多。