Как упорядочить структуры с неизвестными строковыми полями длины в C # - PullRequest
8 голосов
/ 30 января 2011

Я получаю массив байтов, мне нужно распаковать его в C # struct.Я знаю тип структуры, в ней есть несколько строковых полей.Строки в байтовом массиве выглядят так: два первых байта - это длина строки, а затем сама строка.Я не знаю длину струн.Я знаю, что его Unicode!

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class User
{
  int Id;//should be 1
  String UserName;//should be OFIR
  String FullName;//should be OFIR
}

массив байтов выглядит так: 00,00,01,00, 00,00,08,00, 4F, 00,46,00,49,00, 52,00, 00,00,08,00, 4F, 00,46,00,49,00,52,00,

Я также нашел эту ссылку с той же проблемой нерешенной: загрузка двоичногоданные в структуру

Спасибо всем, Офир

Ответы [ 2 ]

3 голосов
/ 05 февраля 2011

Я бы сделал это с BinaryReader. Это будет идти по следующим направлениям:

Foo ReadFoo(Byte[] bytes)
{
     Foo foo = new Foo();
     BinaryReader reader = new BinaryReader(new MemoryStream(bytes));
     foo.ID = reader.ReadUInt32();
     int userNameCharCount = reader.ReadUInt32();
     foo.UserName = new String(reader.ReadChars(userNameCharCount));

     int fullNameCharCount = reader.ReadUInt32();
     foo.FullName = new String(reader.ReadChars(fullNameCharCount));
     return foo;
}

Обратите внимание, что это не будет работать напрямую для предоставленного вами примера байтового массива. Количество символов и поле идентификатора не соответствуют стандартному порядку байтов или порядков байтов. Может случиться так, что поля будут 16-битными, и к ним будут добавлены 16-битные поля заполнения. Кто породил этот поток?

Но точный формат не слишком важен для этой стратегии, так как вы можете просто изменить ReadInt32 на ReadInt16, изменить их порядок, что угодно, чтобы это работало.

Мне не нравятся атрибуты сериализатора. Это потому, что он связывает ваши внутренние структуры данных с тем, как они обмениваются. Это ломается, если вам нужно поддерживать несколько версий формата данных.

0 голосов
/ 02 февраля 2011

Это не ответ (пока), а вопрос / комментарий со значительным количеством кода для обратной связи.Как вы интерпретируете свой байтовый массив?Разбей это.

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct Foo
{
    public int id;

    //[MarshalAs(UnmanagedType.BStr)]
    //public string A;

    //[MarshalAs(UnmanagedType.BStr)]
    //public string B;
}

static void Main(string[] args)
{
    byte[] bits = new byte[] {
        0x00, 0x00, 
        0x01, 0x00, 
        0x00, 0x00, 
        0x08, 0x00,     // Length prefix?               
        0x4F, 0x00,     // Start OFIR?
        0x46, 0x00, 
        0x49, 0x00,     
        0x52, 0x00,     
        0x00, 0x00, 
        0x08, 0x00,     // Length prefix?
        0x4F, 0x00,     // Start OFIR?
        0x46, 0x00, 
        0x49, 0x00, 
        0x52, 0x00 };   

    GCHandle pinnedPacket = GCHandle.Alloc(bits, GCHandleType.Pinned);
    Foo msg = (Foo)Marshal.PtrToStructure(
        pinnedPacket.AddrOfPinnedObject(),
        typeof(Foo));
    pinnedPacket.Free();
}
...