如何从BinaryReader简化网络字节顺序转换?

时间:2020-03-06 14:37:40  来源:igfitidea点击:

System.IO.BinaryReader读取小端格式的值。

我有一个C应用程序连接到服务器端的专有网络库。就像人们期望的那样,服务器端将所有内容按网络字节顺序向下发送,但是我发现在客户端进行处理很麻烦,尤其是对于无符号值。

UInt32 length = (UInt32)IPAddress.NetworkToHostOrder(reader.ReadInt32());

这是我想出的从流中获取正确的无符号值的唯一方法,但这似乎既尴尬又丑陋,而且我还没有测试这是否会截断高阶值,以便做有趣的BitConverter东西。

我是否缺少某种方法来避免在每次读取时进行这些丑陋的转换,而在整个过程中写一个包装器呢?看来读者应该有一个endian-ness选项,以使这种事情变得更简单,但我还没有遇到任何问题。

解决方案

我构建了一个自定义BinaryReader来处理所有这些问题。它可以作为我的Nextem库的一部分使用。它还具有定义二进制结构的非常简单的方法,我认为这对我们有帮助-请查看示例。

注意:目前仅在SVN中使用,但非常稳定。如有任何疑问,请发送电子邮件至cody_dot_brocious_at_gmail_dot_com。

没有内置转换器。这是我的包装器(如我们所见,我仅实现了我需要的功能,但是结构很容易更改为我们喜欢的样子):

/// <summary>
/// Utilities for reading big-endian files
/// </summary>
public class BigEndianReader
{
    public BigEndianReader(BinaryReader baseReader)
    {
        mBaseReader = baseReader;
    }

    public short ReadInt16()
    {
        return BitConverter.ToInt16(ReadBigEndianBytes(2), 0);
    }

    public ushort ReadUInt16()
    {
        return BitConverter.ToUInt16(ReadBigEndianBytes(2), 0);
    }

    public uint ReadUInt32()
    {
        return BitConverter.ToUInt32(ReadBigEndianBytes(4), 0);
    }

    public byte[] ReadBigEndianBytes(int count)
    {
        byte[] bytes = new byte[count];
        for (int i = count - 1; i >= 0; i--)
            bytes[i] = mBaseReader.ReadByte();

        return bytes;
    }

    public byte[] ReadBytes(int count)
    {
        return mBaseReader.ReadBytes(count);
    }

    public void Close()
    {
        mBaseReader.Close();
    }

    public Stream BaseStream
    {
        get { return mBaseReader.BaseStream;  }
    }

    private BinaryReader mBaseReader;
}

基本上,ReadBigEndianBytes会执行艰苦的工作,并将其传递给BitConverter。如果我们读取大量字节,将会有一定的问题,因为这将导致大量的内存分配。