将字节组合成逻辑值

Combining bytes into logical values

我正在以(预期的)以下格式取回数据:

\u0001\u0001\u0004[=10=]\u0001[=10=][=10=][=10=]

每个段代表一个字节。前两段\u0001\u0001代表服务版本号,后两段\u0004[=13=]代表状态码,最后4u0001[=14=][=14=][=14=]代表请求id。

如何将我知道的字段组合在一起并从结果中得出逻辑值?例如,状态码 \u0004[=13=] 应该是一个 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 = "\u0001\u0001\u0004[=11=]\u0001[=11=][=11=][=11=]";

// 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 上面的 post;如果你想变得非常花哨,你可以做一个 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 = "\u0001\u0001\u0004[=11=]\u0001[=11=][=11=][=11=]";

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