开发者

c# Stream Reading and Deserialization

开发者 https://www.devze.com 2023-04-02 08:11 出处:网络
I have this code: public static List<ReplicableObject> ParseStreamForObjects(Stream stream) { List<ReplicableObject> result = new List<ReplicableObject>();

I have this code:

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;
}

Unfortunately, the stream object is always going to be a TCP stream, which means no seek operations. So how can I check to make sure that I'm not over-running the stream where I've put the // HERE comments?


I don't think there's any way to query a NetworkStream to find the data you're looking for. What you'll probably need to do is buffer whatever data the stream makes available into another data structure, then parse objects out of that structure once you know it's got enough bytes in it.

The NetworkStream class provides a DataAvailable property that tells you if any data is available to be read, and the Read() method returns a value indicating how many bytes it actually retrieved. You should be able to use those values to do the buffering you need.


See Mr. Skeets page

Sometimes, you don't know the length of the stream in advance (for instance a network stream) and just want to read the whole lot into a buffer. Here's a method to do just that:

/// <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);
        }
    }
}

This should give you some ideas. Once you have the byte array, checking the Length will be easy to do.

In your example, it would look something like this:

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;
...
0

精彩评论

暂无评论...
验证码 换一张
取 消