go - 在 go 中按顺序将 protobuf 消息写入文件

标签 go serialization protocol-buffers gob

我有大量类似的对象(大约数百 GB),我需要对其进行序列化并按顺序写入文件,然后以相同的顺序读取它。如何在golang的protobuf(gogo proto)中做到这一点? Gob 有一个可以写入 io.Writer 的编码器,但 protobuf 没有类似的东西。可能是 protobuf 不是为此目的的最佳选择?我需要良好的性能和低内存分配。

最佳答案

If you want to write multiple messages to a single file or stream, it is up to you to keep track of where one message ends and the next begins. The Protocol Buffer wire format is not self-delimiting, so protocol buffer parsers cannot determine where a message ends on their own. The easiest way to solve this problem is to write the size of each message before you write the message itself. When you read the messages back in, you read the size, then read the bytes into a separate buffer, then parse from that buffer.



Source

1. 编写 Protobuf

将您的 protobuf 编码为 []byte并调用Write连同您要写入的文件为 io.Writer .这将写入 msg 的长度到io.Writer写之前msg本身。
func Write(w io.Writer, msg []byte) error {
    buf := make([]byte, 4)
    binary.LittleEndian.PutInt32(buf, Uint32(len(msg)))

    if _, err := w.Write(buf); err != nil {
        return err
    }

    if _, err := w.Write(msg); err != nil {
        return err
    }
}

2. 阅读 Protobuf

当你想读出另一边的 protobufs 时,打开文件并将其作为 io.Reader 传入。 .这会从文件中提取大小,然后将该字节数读入 msg缓冲并返回。
func Read(r io.Reader) ([]byte, error) {
    buf := make([]byte, 4)
    if _, err := io.ReadFull(r, buf); err != nil {
        return nil, err
    }

    size := binary.LittleEndian.Uint32(buf)

    msg := make([]byte, size)
    if _, err := io.ReadFull(r, msg); err != nil {
        return nil, err
    }

    return msg, err
}
*os.File输入 Go 满足 io.Readerio.Writer接口(interface),所以你不应该遇到任何问题。

感谢@Brits 指出这一点。

祝你好运!

关于go - 在 go 中按顺序将 protobuf 消息写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59163455/

相关文章:

oop - 使用反射调用方法并返回值

php - Symfony Serializer 无法在反序列化时处理 Doctrine Id

c# - 意外的子类型 : MyNamespace. MyInheritedClass

input - Golang - 读取 Os.stdin 输入但不回显

go - 使用 part.Read 每 block 读取超过 4096 字节

java - Redis 对象序列化向后兼容性

python - 如何将多维 h5py 数据集复制到平面一维 Python 列表而不制作任何中间副本?

arrays - 包含多个特定类型的固定大小数组?

java - GZIP Streams 的序列化/反序列化不一致