依次将protobuf消息写入go中的文件

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

lovers_php 回答:依次将protobuf消息写入go中的文件

  

如果您想将多个消息写入单个文件或流,则它将   由您决定跟踪一条消息的结尾和下一条消息的结尾   开始。协议缓冲区连线格式不是自定界的,因此   协议缓冲区解析器无法确定消息在其何处结束   拥有。解决此问题的最简单方法是写下   每条消息,然后再编写消息本身。当您阅读   消息返回时,您读取大小,然后将字节读取到   单独的缓冲区,然后从该缓冲区进行解析。

Source

1。编写Protobuf

将您的probubuf编组到[]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

当您想读出另一侧的原型缓冲区时,请打开文件并将其作为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 _,msg); err != nil {
        return nil,err
    }

    return msg,err
}

Go中的*os.File类型同时满足io.Readerio.Writer接口,因此您不会遇到任何问题。

@Brits指出了这一点。

祝你好运!

本文链接:https://www.f2er.com/2983204.html

大家都在问