【问题标题】:How can I add separators between different records in a bincoded file?如何在 bincoded 文件中的不同记录之间添加分隔符?
【发布时间】:2018-05-07 14:25:59
【问题描述】:

我有关注struct

struct Employee {
    id: u64,
    name: String,
}

我正在使用以下代码对其进行序列化,然后将序列化的字节数组写入文件:

let emp = Employee {
    id: 1546,
    name: "abcd".to_string(),
};

let mut file = OpenOptions::new()
    .read(true)
    .write(true)
    .create(true)
    .open("hello.txt")
    .unwrap();

let initial_buf = &bincode::serialize(&emp).unwrap();

println!("Initial Buf: {:?}", initial_buf);

file.write(&initial_buf);
file.write(&[b'\n']);
file.flush();

file.seek(SeekFrom::Start(0)).unwrap();

let mut final_buf: Vec<u8> = Vec::new();

let mut reader = BufReader::new(file);

reader.read_until(b'\n', &mut final_buf).unwrap();

println!("Final Buf: {:?}", final_buf);

我得到以下输出:

Initial Buf: [10, 6, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99, 100]
Final Buf: [10]

【问题讨论】:

  • 换行符 (ascii 10) 在 initial_buf 中,所以很明显它来自 serialize,而您没有提供。
  • serializebincode::serialize

标签: serialization rust deserialization serde


【解决方案1】:

Bincode 的约定是你给它一个序列化的值,它给你返回字节。合约不保证你返回的字节不能包含换行符。

在您的数据中,整数 1546 是 0x60A,表示为字节 [10, 6, 0, 0]

您应该能够在没有任何分隔符的情况下使用 Bincode 数据。 bincode::deserialize_from 函数会知道在哪里停止阅读。

【讨论】:

  • 这种方法的问题是文件中的虚拟光标可以在任何地方。例如,如果我想从文件中间读取一条随机记录,我该如何寻找该记录的起始位置?为此,我必须分别存储所有记录的起始偏移量。
  • 如果您需要查找的能力,您可以为每条记录添加长度前缀。一般来说,我希望这种方法比使用换行符更有效 - 因为为了寻找文件的特定“行”,您需要查看该行之前的每个字节以确定它是否是换行符字节,而使用长度前缀,您可以一次读取跳过整条记录。
  • 另外,如果我们能以某种方式将它添加到 bincode 本身中,那就太好了。 BSON在开头添加int32来指定编码字节数组的长度。
猜你喜欢
  • 2015-12-08
  • 1970-01-01
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 2012-10-14
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多