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

发布于 2024-10-20 17:09:11 字数 756 浏览 1 评论 0原文

我有这个十六进制数据:

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 SERVICE
{
    unsigned char c;
    unsigned char size;
    unsigned char headcode;
    unsigned char Type;
    unsigned short Port;
    char ServiceName[50];
    unsigned short ServiceCode;
};

我的问题是: 如何从数据中获取 ServiceName、Port 等...?

抱歉我的英语不好

I have this hexadecimal data:

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

I have 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;
};

My question is: How to get from data ServiceName, Port and etc...?

Sorry for my bad english

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吃兔兔 2024-10-27 17:09:11

这是一种实现方法:

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

假设二进制数组使用与您的体系结构相同的字节顺序。如果不是这种情况,您可以使用 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;
}

Here is one way to do it:

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

This assumes, that the binary array uses the same Endianess as your architecture. If that is not the case you can use the EndianBinaryReader from the MiscUtil library.

Edit: this is also a nice solution, that avoids the reader altogether. You can't directly specify the encoding to use for the string however and the memory layout of the structure has to match the layout used in the byte array.

[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;
}
冧九 2024-10-27 17:09:11

首先,确定您的字节编码是小端还是大端。然后,将字段一一解压(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#。

First, Decide if your byte encoding is little or big endian. Then, unpack fields one by one (C example)

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++];

NOTE: This is usually written as moving the data pointer instead of using "i" as an index, but I left it in this form for ease of moving to C#.

猫九 2024-10-27 17:09:11

从问题中,我无法找出你想如何实现这一点,但这是 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;

}

From the question, I could not find out how you want to achieve this but this is the C# structure.

You can define the structure as below

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;

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文