【问题标题】:c# Stream Reading and Deserializationc# 流读取和反序列化
【发布时间】:2011-09-01 17:09:21
【问题描述】:

我有这个代码:

public static List<ReplicableObject> ParseStreamForObjects(Stream stream) 
{
   List<ReplicableObject> result = new List<ReplicableObject>();
   while (true) 
   {
      // HERE I want to check that there's at least four bytes left in the stream
      BinaryReader br = new BinaryReader(stream);
      int length = br.ReadInt32();
      // HERE I want to check that there's enough bytes left in the stream
      byte[] bytes = br.ReadBytes(length);
      MemoryStream ms = new MemoryStream(bytes);
      ms.Position = 0;
      result.Add((ReplicableObject) Formatter.Deserialize(ms));
      ms.Close();
      br.Close();
   }
   return result;
}

不幸的是,流对象总是一个 TCP 流,这意味着没有查找操作。那么我如何检查以确保我没有过度运行我放置 // HERE cmets 的流?

【问题讨论】:

  • 您是否可以控制通过网络发送的内容?如果是,那么你可以简单地在另一边写下你在序列化你的对象时发送了多少字节......
  • 是的,我有,而且我有(见'int length = br.ReadInt32()'这一行)。但现在我得到一个新的错误。我应该为它提出一个新问题吗?
  • @Motig - 是的,如果是新问题,您应该创建一个新问题

标签: c# serialization tcp stream


【解决方案1】:

我认为没有任何方法可以查询NetworkStream 来查找您要查找的数据。您可能需要做的是将流提供的任何数据缓冲到另一个数据结构中,然后一旦您知道其中有足够的字节,就从该结构中解析出对象。

NetworkStream 类提供了一个DataAvailable 属性,告诉您是否有任何数据可供读取,Read() 方法返回一个值,指示它实际检索到的字节数。您应该能够使用这些值来进行所需的缓冲。

【讨论】:

    【解决方案2】:

    见斯基茨先生page

    有时,您事先不知道流的长度(例如网络流),而只想将全部内容读入缓冲区。这是一种方法:

    /// <summary>
    /// Reads data from a stream until the end is reached. The
    /// data is returned as a byte array. An IOException is
    /// thrown if any of the underlying IO calls fail.
    /// </summary>
    /// <param name="stream">The stream to read data from</param>
    public static byte[] ReadFully (Stream stream)
    {
        byte[] buffer = new byte[32768];
        using (MemoryStream ms = new MemoryStream())
        {
            while (true)
            {
                int read = stream.Read (buffer, 0, buffer.Length);
                if (read <= 0)
                    return ms.ToArray();
                ms.Write (buffer, 0, read);
            }
        }
    }
    

    这应该会给你一些想法。一旦你有了字节数组,检查Length 就很容易了。

    在您的示例中,它看起来像这样:

    int bytes_to_read = 4;
    byte[] length_bytes = new byte[bytes_to_read];
    int bytes_read = stream.Read(length_bytes, 0, length_bytes.Length);
    // Check that there's at least four bytes left in the stream
    if(bytes_read != bytes_to_read) break;
    int bytes_in_msg = BitConverter.ToInt32(length_bytes);
    byte[] msg_bytes = new byte[bytes_in_msg];
    bytes_read = stream.Read(msg_bytes, 0, msg_bytes.Length);
    // Check that there's enough bytes left in the stream
    if(bytes_read != bytes_in_msg ) break;
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-06
      • 2015-09-09
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2012-02-02
      相关资源
      最近更新 更多