【问题标题】:Why does CodedInputStream set stream position to end?为什么 CodedInputStream 将流位置设置为结束?
【发布时间】:2016-02-17 11:09:24
【问题描述】:

我在 c# 中使用协议缓冲区 3。我试图通过流弹跳以找到每条消息的起始位置,而实际上没有反序列化消息。所有消息都使用WriteDelimitedTo 写入流。

然后我使用此代码尝试从长度标记跳转:

_map = new List<int>();
_stream.Seek(0, SeekOrigin.Begin);

var codedStream = new CodedInputStream(_stream);

while (_stream.Position < _stream.Length)
{
    var length = codedStream.ReadInt32();

    _map.Add((int) _stream.Position);

    _stream.Seek(length, SeekOrigin.Current);
}

但是,当我执行codedStream.ReadInt32() 时,流位置设置为末尾,而不仅仅是 varint32 之后的下一个字节。

【问题讨论】:

  • 什么是_stream?它包含什么? 是否包含多个整数?此外,网络流通常无法在不先读取所有内容的情况下确定其长度。通过检查 .Length 而不是 EOF 或 Read 的结果,您可能正在阅读并丢弃所有内容。这就是为什么大多数 Stream 样本会检查读取的字节数,而不是大小。
  • 只是一个内存流。是的,它在单元测试中。我写了 3 条消息并尝试跳过长度前缀。但由于某种原因,CodedInputStream 不只是读取 varin32 的字节,它还寻找基本流到最后。
  • 不要尝试操纵底层流,而是使用CodedInputStream.IsAtEnd。接触底层流是一个坏主意——你已经用另一个包裹了原始流,它可能会缓冲或以其他方式处理它的底层流。查看CodedInputStream的代码,似乎确实如此。
  • 我不知道它是否可以方便地在您正在使用的特定库中使用,但绝对有可能以非缓冲方式读取 varint (在不过度阅读的情况下使用数据的想法),然后读取长度限制的流或使用长度限制的阅读器。 - see here(另一半见 L112-L1142);如果这两种方法有用,请随意借用
  • 是的,我把你的代码作为解决方案放在了我的脑海里。

标签: c# protocol-buffers


【解决方案1】:

这种行为是由于CodedInputStream 将原始流缓冲为you can see in the source code。它可能不适合手动读取和通过流搜索。另一种方法是使用 Marc Gravell 的部分源代码来读取varintavailable here,并直接移动原始流。

【讨论】:

    猜你喜欢
    • 2019-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 2015-08-29
    • 2011-08-11
    相关资源
    最近更新 更多