C# int到字节[]在网络上的一致性

C# int到字节[]在网络上的一致性,c#,serialization,endianness,C#,Serialization,Endianness,我有一个结构,可以在所有地方使用,我将它作为byteArray存储在hd上,也可以发送到其他平台 我曾经通过获取结构的字符串版本并在序列化过程中使用getBytes(utf-8)和getString(utf-8)来实现这一点。有了这个,我想我避免了小的和大的endian问题 然而,这是相当大的开销,我现在使用这个: public static explicit operator byte[] (Int3 self) { byte[] int3ByteArr = new

我有一个结构,可以在所有地方使用,我将它作为byteArray存储在hd上,也可以发送到其他平台

我曾经通过获取结构的字符串版本并在序列化过程中使用getBytes(utf-8)和getString(utf-8)来实现这一点。有了这个,我想我避免了小的和大的endian问题

然而,这是相当大的开销,我现在使用这个:

 public static explicit operator byte[] (Int3 self)
    {

        byte[] int3ByteArr = new byte[12];//4*3
        int x = self.x;
        int3ByteArr[0] = (byte)x;
        int3ByteArr[1] = (byte)(x >> 8);
        int3ByteArr[2] = (byte)(x >> 0x10);
        int3ByteArr[3] = (byte)(x >> 0x18);
        int y = self.y;
        int3ByteArr[4] = (byte)y;
        int3ByteArr[5] = (byte)(y >> 8);
        int3ByteArr[6] = (byte)(y >> 0x10);
        int3ByteArr[7] = (byte)(y >> 0x18);
        int z = self.z;
        int3ByteArr[8] = (byte)z;
        int3ByteArr[9] = (byte)(z >> 8);
        int3ByteArr[10] = (byte)(z >> 0x10);
        int3ByteArr[11] = (byte)(z >> 0x18);

        return int3ByteArr;
    }



public static explicit operator Int3(byte[] self)
        {

            int x = self[0] + (self[1] << 8) + (self[2] << 0x10) + (self[3] << 0x18);
            int y = self[4] + (self[5] << 8) + (self[6] << 0x10) + (self[7] << 0x18);
            int z = self[8] + (self[9] << 8) + (self[10] << 0x10) + (self[11] << 0x18);

            return new Int3(x, y, z);

        }
公共静态显式运算符字节[](Int3 self)
{
字节[]int3ByteArr=新字节[12];//4*3
int x=self.x;
int3ByteArr[0]=(字节)x;
int3ByteArr[1]=(字节)(x>>8);
int3ByteArr[2]=(字节)(x>>0x10);
int3ByteArr[3]=(字节)(x>>0x18);
int y=self.y;
int3ByteArr[4]=(字节)y;
int3ByteArr[5]=(字节)(y>>8);
int3ByteArr[6]=(字节)(y>>0x10);
int3ByteArr[7]=(字节)(y>>0x18);
intz=self.z;
int3ByteArr[8]=(字节)z;
int3ByteArr[9]=(字节)(z>>8);
int3ByteArr[10]=(字节)(z>>0x10);
int3ByteArr[11]=(字节)(z>>0x18);
返回int3ByteArr;
}
公共静态显式运算符Int3(字节[]self)
{

int x=self[0]+(self[1]是的。如果更改endianness,保留位顺序的序列化将遇到麻烦

取整数385

在bigendian系统中,它将存储为

000000000000000 110000001

把它解读为littleendian会把它解读为 100000011000000000000000 并反译为8486912

如果您使用BitConverter类,则会有一个book属性要求系统的endianness。BitConverter还可以为您生成位数组

您必须根据序列化或反序列化系统的endianness来决定使用endianness和反转字节数组


实际上是非常详细的。为了简单起见,这里他们使用了数组。反转。我不确定为了进行位操作而对字节进行的转换是否是最快的转换方式,但这很容易进行基准测试。

是的。通过更改endianness,保留位顺序的序列化将被取消他陷入困境

取整数385

在bigendian系统中,它将存储为

000000000000000 110000001

把它解读为littleendian会把它解读为 100000011000000000000000 并反译为8486912

如果您使用BitConverter类,则会有一个book属性要求系统的endianness。BitConverter还可以为您生成位数组

您必须根据序列化或反序列化系统的endianness来决定使用endianness和反转字节数组


事实上,转换非常详细。为了简单起见,这里他们使用了
数组。反向
。我不确定为了进行位操作而对字节进行转换是否是最快的转换方式,但这很容易进行基准测试。

当应用程序在系统wh上运行时,您当前的方法将不起作用我用Big-Endian。在这种情况下,你根本不需要重新排序

您无需自行反转字节数组
您不需要自己检查系统的持久性

静态方法
IPAddress.HostToNetworkOrder
将整数转换为具有大端顺序的整数

静态方法
IPAddress.NetworkToHostOrder
将整数转换为系统使用的整数

这些方法将检查系统的Endianness,并执行/或不执行整数的重新排序

使用
位转换器

public struct ThreeIntegers
{
    public int One;
    public int Two;
    public int Three;
}

public static byte[] ToBytes(this ThreeIntegers value )
{
    byte[] bytes = new byte[12];
    byte[] bytesOne = IntegerToBytes(value.One);
    Buffer.BlockCopy(bytesOne, 0, bytes, 0, 4);

    byte[] bytesTwo = IntegerToBytes(value.Two);
    Buffer.BlockCopy(bytesTwo , 0, bytes, 4, 4);

    byte[] bytesThree = IntegerToBytes(value.Three);
    Buffer.BlockCopy(bytesThree , 0, bytes, 8, 4);

    return bytes;
} 

public static byte[] IntegerToBytes(int value)
{
    int reordered = IPAddress.HostToNetworkOrder(value);
    return BitConverter.GetBytes(reordered);
}
以及从字节到结构的转换

public static ThreeIntegers GetThreeIntegers(byte[] bytes)
{
    int rawValueOne = BitConverter.ToInt32(bytes, 0);
    int valueOne = IPAddress.NetworkToHostOrder(rawValueOne);

    int rawValueTwo = BitConverter.ToInt32(bytes, 4);
    int valueTwo = IPAddress.NetworkToHostOrder(rawValueTwo);

    int rawValueThree = BitConverter.ToInt32(bytes, 8);
    int valueThree = IPAddress.NetworkToHostOrder(rawValueThree);

    return new ThreeIntegers(valueOne, valueTwo, valueThree);
}
如果要使用
BinaryReader
BinaryWriter
保存并发送到其他平台,则可以删除位转换器和字节数组操作

// BinaryWriter.Write have overload for Int32
public static void SaveThreeIntegers(ThreeIntegers value)
{
    using(var stream = CreateYourStream())
    using (var writer = new BinaryWriter(stream))
    {
        int reordredOne = IPAddress.HostToNetworkOrder(value.One);
        writer.Write(reorderedOne);

        int reordredTwo = IPAddress.HostToNetworkOrder(value.Two);
        writer.Write(reordredTwo);

        int reordredThree = IPAddress.HostToNetworkOrder(value.Three);
        writer.Write(reordredThree);
    }
}
用于读取值

public static ThreeIntegers LoadThreeIntegers()
{
    using(var stream = CreateYourStream())
    using (var writer = new BinaryReader(stream))
    {
        int rawValueOne = reader.ReadInt32();
        int valueOne = IPAddress.NetworkToHostOrder(rawValueOne);

        int rawValueTwo = reader.ReadInt32();
        int valueTwo = IPAddress.NetworkToHostOrder(rawValueTwo);

        int rawValueThree = reader.ReadInt32();
        int valueThree = IPAddress.NetworkToHostOrder(rawValueThree);
    }
}
当然,您可以重构上述方法并获得更干净的解决方案。

或者为
BinaryWriter
BinaryReader

添加扩展方法,当应用程序在使用Big-Endian的系统上运行时,您当前的方法将不起作用。在这种情况下,您根本不需要重新排序

您无需自行反转字节数组
您不需要自己检查系统的持久性

静态方法
IPAddress.HostToNetworkOrder
将整数转换为具有大端顺序的整数

静态方法
IPAddress.NetworkToHostOrder
将整数转换为系统使用的整数

这些方法将检查系统的Endianness,并执行/或不执行整数的重新排序

使用
位转换器

public struct ThreeIntegers
{
    public int One;
    public int Two;
    public int Three;
}

public static byte[] ToBytes(this ThreeIntegers value )
{
    byte[] bytes = new byte[12];
    byte[] bytesOne = IntegerToBytes(value.One);
    Buffer.BlockCopy(bytesOne, 0, bytes, 0, 4);

    byte[] bytesTwo = IntegerToBytes(value.Two);
    Buffer.BlockCopy(bytesTwo , 0, bytes, 4, 4);

    byte[] bytesThree = IntegerToBytes(value.Three);
    Buffer.BlockCopy(bytesThree , 0, bytes, 8, 4);

    return bytes;
} 

public static byte[] IntegerToBytes(int value)
{
    int reordered = IPAddress.HostToNetworkOrder(value);
    return BitConverter.GetBytes(reordered);
}
以及从字节到结构的转换

public static ThreeIntegers GetThreeIntegers(byte[] bytes)
{
    int rawValueOne = BitConverter.ToInt32(bytes, 0);
    int valueOne = IPAddress.NetworkToHostOrder(rawValueOne);

    int rawValueTwo = BitConverter.ToInt32(bytes, 4);
    int valueTwo = IPAddress.NetworkToHostOrder(rawValueTwo);

    int rawValueThree = BitConverter.ToInt32(bytes, 8);
    int valueThree = IPAddress.NetworkToHostOrder(rawValueThree);

    return new ThreeIntegers(valueOne, valueTwo, valueThree);
}
如果要使用
BinaryReader
BinaryWriter
保存并发送到其他平台,则可以删除位转换器和字节数组操作

// BinaryWriter.Write have overload for Int32
public static void SaveThreeIntegers(ThreeIntegers value)
{
    using(var stream = CreateYourStream())
    using (var writer = new BinaryWriter(stream))
    {
        int reordredOne = IPAddress.HostToNetworkOrder(value.One);
        writer.Write(reorderedOne);

        int reordredTwo = IPAddress.HostToNetworkOrder(value.Two);
        writer.Write(reordredTwo);

        int reordredThree = IPAddress.HostToNetworkOrder(value.Three);
        writer.Write(reordredThree);
    }
}
用于读取值

public static ThreeIntegers LoadThreeIntegers()
{
    using(var stream = CreateYourStream())
    using (var writer = new BinaryReader(stream))
    {
        int rawValueOne = reader.ReadInt32();
        int valueOne = IPAddress.NetworkToHostOrder(rawValueOne);

        int rawValueTwo = reader.ReadInt32();
        int valueTwo = IPAddress.NetworkToHostOrder(rawValueTwo);

        int rawValueThree = reader.ReadInt32();
        int valueThree = IPAddress.NetworkToHostOrder(rawValueThree);
    }
}
当然,您可以重构上述方法并获得更干净的解决方案。

或者添加为
BinaryWriter
BinaryReader

的扩展方法,使用
IPAddress.HostToNetwork
方法。当前,如果您的软件将运行在大的Endian系统上,则最终通过网络发送的Endian字节数很少。使用
IPAddress.HostToNetwork
方法。当前,如果您的软件将是ru在大的ENDDian系统上运行-最终通过网络发送小的ENDDian字节。所以我可以检查一个系统是否是小的ENDDian,当它是时,…我做我上面所做的,但不是从索引0..3而是从索引3..1?这听起来很合理,是的。但是记住对反向翻译进行同样的检查。这样我就可以检查一个系统是否是l