Android Protobuf流(延迟序列化)API

Android Protobuf流(延迟序列化)API,android,xml,json,model,protocol-buffers,Android,Xml,Json,Model,Protocol Buffers,我们有一个Android应用程序,它使用协议缓冲区来存储应用程序数据。数据格式(大致)是一个单独的protobuf(“容器”),其中包含一个protobuf(“项目”)列表作为重复字段: message Container { repeated Item item = 1; } 当我们想要保存对某个项的更改时,我们必须重新创建protobuf容器,将所有项添加到其中,然后序列化它并将其写入文件 这种方法的问题在于,它可能会使保存时使用的内存增加三倍,因为数据必须首先从模型类复制到pro

我们有一个Android应用程序,它使用协议缓冲区来存储应用程序数据。数据格式(大致)是一个单独的protobuf(“容器”),其中包含一个protobuf(“项目”)列表作为重复字段:

message Container {
    repeated Item item = 1;
}
当我们想要保存对某个项的更改时,我们必须重新创建protobuf容器,将所有项添加到其中,然后序列化它并将其写入文件

这种方法的问题在于,它可能会使保存时使用的内存增加三倍,因为数据必须首先从模型类复制到protobuf生成器,然后在protobuf序列化时复制到字节数组,所有这些都是在将数据写入文件流之前进行的

我们想要的是一种创建protobuf容器并将其延迟序列化到流的方法,然后简单地将每个protobuf项(从模型数据创建)添加到容器中,然后将其序列化并写入流,而不是将所有项保留在内存中,直到在内存中创建整个容器

有没有办法构建protobuf并将其延迟序列化为流?


如果没有正式的方法,有没有图书馆可以提供帮助?有人对如何用其他方式解决这个问题有什么建议或想法吗?可供选择的数据格式或技术(例如JSON或包含protobufs的XML)使之成为可能?

没有这样的事情。protobuf是一种压缩结构。为了有效地做到这一点,它需要所有的数据。您必须自己添加“流媒体协议”。可能每N个项目发送一个protobuf消息。

用于序列化:

protobuf是一种可追加的格式,合并单个项,追加重复项

因此,要将一个序列作为惰性流写入,只需重复写入列表中只有一项的相同结构:序列化一个200 x“Container with 1 item”的序列与序列化1 x“Container with 200 Items”完全相同

所以:就这么做吧


对于反序列化:

这在技术上很容易作为一个流来阅读——然而,这一切都取决于您使用的是哪个库。例如,我在protobuf net(一个.net/C#实现)中将其公开为
序列化器.DeserializeItems
,它读取(完全延迟/流式)类型为
T
的消息序列,前提是它们采用您在问题中描述的形式(因此,
Serializer.DeserializeItems
将是取代
Serializer.Deserialize
的流式方式-protobuf中实际上不存在最外层的对象)

如果此功能不可用,但您可以访问原始读取器API,则需要执行以下操作:


  • 读取标题的一个变量-这将是值10(0x0A),即“(1在协议缓冲区的正常java版本中,存在分隔文件,您可以在其中一次写入一个协议缓冲区。我不确定它是否在Android版本中

     aLocation.writeDelimitedTo(out);
    
    正如Marc所指出的,它很容易实现;只需在后面写一个长度 序列化字节。在prortocol缓冲区的普通(非android)java版本中,您也可以这样做(您必须序列化到字节数组或类似的东西)


    在其他协议缓冲区版本中可能会出现一些情况

    实际上,具有重复内部列表的外部对象是一个基本序列,可以(取决于库)以纯流方式进行反序列化。甚至有讨论(尽管从未发生过)将其形式化为允许流式消息处理的API,用于通过网络流传递多个异构消息,其布局与问题中的布局相同protobuf库对此不支持。在编写时,每个库都可以这样做。因为protobuf是可追加的/mergAbeable,不可能做不到这一点。你似乎在谈论反序列化。我有充分的证据表明OP正在谈论序列化。你知道有没有Java库支持这一点吗?@bacar抱歉,但我不使用Java-我不熟悉公开的API。谢谢。我注意到有人声称支持streaming、 虽然还没有玩过它,但实际上我并不完全清楚protostuff实际上是什么,从项目页面上看,它是Google java protobuf库的扩展,还是它的替代品。@bacar据我所知(没有使用过它),它允许与pojo类型等一起使用。类似于protobuf net在.net中的功能(编辑了我的答案,包括序列化和反序列化)
    private CodedOutputStream codedStream = null;
    
    
    public void write(byte[] bytes) throws IOException {
        if (bytes != ConstClass.EMPTY_BYTE_ARRAY) {
            codedStream.writeRawVarint32(bytes.length);
            codedStream.writeRawBytes(bytes);
            codedStream.flush();
        }
    }
    
        private CodedInputStream coded;
    
    public byte[] read() throws IOException {
        if (coded == null) {
            throw new IOException("Reader has not been opened !!!");
        }
        if (coded.isAtEnd()) {
            return null;
        }
        return coded.readBytes().toByteArray();