C#从十六进制数据中获取信息

时间:2011-03-06 21:06:24

标签: c++ hex

我有这个十六进制数据:

byte[] data = new Byte[] {
    0xC1, 0x3A, 0x00, 0x01, 0x5D, 0xDA, 0x47, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xF0, 0xFC, 0x12, 0x00, 0x00, 0x00
};

我有C ++ struct:

struct SERVICE
{
    unsigned char c;
    unsigned char size;
    unsigned char headcode;
    unsigned char Type;
    unsigned short Port;
    char ServiceName[50];
    unsigned short ServiceCode;
};

我的问题是:如何从数据ServiceName,端口等获取......?

抱歉我的英文不好

3 个答案:

答案 0 :(得分:1)

这是一种方法:

struct SERVICE
{
    public byte c;
    public byte size;
    public byte headcode;
    public byte Type;
    public ushort Port;
    public string ServiceName;
    public ushort ServiceCode;
};

string GetNullTerminatedString(byte[] data, Encoding encoding)
{
    int index = Array.IndexOf(data, (byte)0);
    if (index < 0)
    {
        Debug.WriteLine("No string terminator found.");
        index = data.Length;
    }

    return encoding.GetString(data, 0, index);
}

SERVICE ByteArrayToService(byte[] array, Encoding encoding)
{
    using (MemoryStream stream = new MemoryStream(array))
    {
        using (BinaryReader reader = new BinaryReader(stream))
        {
            SERVICE service = new SERVICE();
            service.c = reader.ReadByte();
            service.size = reader.ReadByte();
            service.headcode = reader.ReadByte();
            service.Type = reader.ReadByte();
            service.Port = reader.ReadUInt16();
            service.ServiceName = GetNullTerminatedString(reader.ReadBytes(50), encoding);
            service.ServiceCode = reader.ReadUInt16();
            return service;
        }
    }
}

void Main(string[] args)
{
    byte[] data = new Byte[]
    {
        0xC1, 0x3A, 0x00, 0x01, 0x5D, 0xDA, 0x47, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0xF0, 0xFC, 0x12, 0x00, 0x00, 0x00
    };

    SERVICE s = ByteArrayToService(data, Encoding.Default);
}

这假定二进制数组使用与您的体系结构相同的Endianess。如果不是这种情况,您可以使用MiscUtil库中的EndianBinaryReader。

编辑:这也是一个很好的解决方案,完全避免了读者。您不能直接指定用于字符串的编码,但结构的内存布局必须与字节数组中使用的布局相匹配。

[StructLayout(LayoutKind.Sequential)]
struct SERVICE
{
    public byte c;
    public byte size;
    public byte headcode;
    public byte Type;
    public ushort Port;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string ServiceName;
    public ushort ServiceCode;
};

SERVICE ByteArrayToService(byte[] array)
{
    GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
    SERVICE service = (SERVICE)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(SERVICE));
    handle.Free();
    return service;
}

答案 1 :(得分:0)

首先,确定您的字节编码是小端还是大端。然后,逐个解压缩字段(C示例)

struct SERVICE s;
int i = 0;
s.c = data[i++];
s.size = data[i++];
s.headcode = data[i++];
s.Type = data[i++];
s.Port = data[i++] << 8 | data[i++]; /* This is where endian matters */
memcpy(s.ServiceName, &data[i], 50);
i += 50;
s.ServiceCode = data[i++] << 8 | data[i++];

注意:这通常写为移动数据指针而不是使用“i”作为索引,但我将其保留为此形式以便于移动到C#。

答案 2 :(得分:0)

从这个问题来看,我无法找到你想要实现的目标,但这是C#结构。

您可以将结构定义如下

public struct Service
{

    public byte C;
    public byte Size;
    public byte HeadCode;
    public byte Type;
    public UInt16 Port;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
    public byte[] values;
    public UInt16 ServiceCode;

}