将字节组合成逻辑值



我以(预期的)以下格式获得数据:

u0001u0001u0004u0001

每个段代表一个字节。前2段u0001u0001表示服务版本号,后2段u0004表示状态码,后4段u0001表示请求id。

我怎样才能把我知道的字段放在一起,并从结果中得到一个逻辑值?例如,状态码u0004应该是signed-short,请求id应该是int。

我摆弄了一下,但我不知道有效性:

byte s1 = 0004;
byte s2 = 0;
short statusCode = (short)(s1 | (s2 << 8));
byte r1 = 0001;
byte r2 = 0;
byte r3 = 0;
byte r4 = 0;
int requestId = (int)(r1 | (r2 << 8) | (r3 << 16) | (r4 << 24));

虽然您的逻辑看起来很好,但手动位移位可能会变得非常繁琐,特别是当您必须处理的数据量增加时。对于8个字节来说,这已经足够简单了,但对于其他所有内容,我建议您考虑将字节直接编组到对象中。

为此,定义一个值类型来解释您的数据:

public struct Data
{
    public short serviceVersion;
    public short statusCode;
    public int requestId;
}

然后,您可以将字符串转换为字节数组,并将其编组为Data对象:

// raw input, as a string
string s = "u0001u0001u0004u0001";
// convert string into byte array
byte[] bytes = Encoding.UTF8.GetBytes(s);
// interpret byte array as `Data` object
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
Data data = (Data)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Data));
handle.Free();
// access the data!
Console.WriteLine(data.serviceVersion); // 257
Console.WriteLine(data.statusCode); // 4
Console.WriteLine(data.requestId); // 1

延续@poke的帖子;如果你想要更花哨一点你可以设置一个union样式的效果

using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct Data
{
    [FieldOffset(0)]
    public short serviceVersion;
    [FieldOffset(2)]
    public short statusCode;
    [FieldOffset(4)]
    public int requestId;
    [FieldOffset(0)]
    public ulong Value;
}

使用Data.Value字段读取所有您关心的位。

另外,使用unsafe可以避免封送。

// raw input, as a string
string s = "u0001u0001u0004u0001";
// convert string into byte array
byte[] bytes = Encoding.UTF8.GetBytes(s);
Data data = new Data();
unsafe
{
    Data* d = &data;
    fixed(byte* b = bytes)
    {
        *d = *((Data*)b);
    }
}

最新更新