首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于protobuf net的部分异步反序列化c#

基于protobuf net的部分异步反序列化c#
EN

Stack Overflow用户
提问于 2013-08-16 07:52:01
回答 1查看 1.4K关注 0票数 1

上下文

我有一个具有以下结构的文件:

代码语言:javascript
运行
复制
[ProtoContract]
public class Data
{
    [ProtoMember(1)]
    public string Header { get; set; }

    [ProtoMember(2)]
    public byte[] Body { get; set; }
}

将数据读写到文件中的代码运行在asp.net mvc webapi上下文中。我试图保持每一个阻塞IO异步,以尽量减少阻塞,并实现最佳的可伸缩性。从文件中读取和写入确实支持ReadAsync、WriteAsync和CopyToAsync。

主体可以相当大(>>标头),而且我只需要读取主体,如果头符合某些特定的标准。

通过使用Deserialize part of a binary file中解释的方法,我可以同步地部分读取和反序列化标头,并以相同的方式读取和反序列化主体。

问题

如何使用异步文件IO进行完全相同的操作,读取和反序列化标头异步以及以相同的方式读取和反序列化主体?

我读过Asynchronous protobuf serialization不是一种选择。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-16 09:26:16

从技术上讲,protobuf字段可能是无序的,但是在大多数情况下(包括您展示的字段),我们可以合理地假设字段是有序的(在这里使它们无序的唯一方法是分别序列化两个半类并连接结果,这在protobuf规范中是有效的)。

因此,我们将得到的是:

  • 表示的变量:字段1,字符串-总是十进制10
  • 表示"a“的静脉曲张,标头的长度
  • "a“字节,UTF-8编码头
  • 表示的变量:字段2,字符串-总是十进制18
  • 表示"b“的字元,表示身体的长度。
  • "b“字节,主体

我们可能会假设"a“是>= 0< int.MaxValue --这意味着编码最多需要5个字节;因此,如果缓冲至少6个字节,就会有足够的信息来知道报头有多大。当然,它在技术上也可以包含身体的一部分,所以你需要保持它!但是,如果您有一个同步过异步的Stream,您可以通过如下方式读取流的这一部分:

代码语言:javascript
运行
复制
int protoHeader = ProtoReader.DirectReadVarintInt32(stream); // 10
int headerLength = ProtoReader.DirectReadVarintInt32(stream);
string header = ProtoReader.DirectReadString(stream, headerLength);

或者,如果“同步超过异步”是棘手的,显式阅读:

代码语言:javascript
运行
复制
static byte[] ReadAtLeast6()
{
    return new byte[] { 0x0A, 0x0B, 0x68, 0x65, 0x6C, 0x6C, 0x6F };
}
static byte[] ReadMore(int bytes)
{
    return new byte[] { 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64 };
}
static void Main()
{
    // pretend we read 7 bytes async
    var data = ReadAtLeast6();
    using (var ms = new MemoryStream())
    {
        ms.Write(data, 0, data.Length);
        ms.Position = 0;
        int protoHeader = ProtoReader.DirectReadVarintInt32(ms); // 10
        int headerLength = ProtoReader.DirectReadVarintInt32(ms); // 11

        int needed = (headerLength + (int)ms.Position) - data.Length; // 6 more
        var pos = ms.Position;
        ms.Seek(0, SeekOrigin.End);
        data = ReadMore(needed);
        ms.Write(data, 0, needed);
        ms.Position = pos;
        string header = ProtoReader.DirectReadString(ms, headerLength);
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18268442

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档