2011-01-30 30 views
8

Obtengo una matriz de bytes, necesito descomprimirla en C# struct. Conozco el tipo de estructura, tiene algunos campos de cadenas. Las cadenas en la matriz de bytes aparecen de esta forma: dos primeros bytes son la longitud de la cadena, luego la cadena misma. No conozco la longitud de las cadenas. ¡Sé que es Unicode!Cómo estructurar estructuras con campos de longitud de longitud desconocida en C#

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

la matriz de bytes se ve así: 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,

también encontré este enlace con el mismo problema sin resolver: loading binary data into a structure

Gracias a todos, Ofir

+0

Ofir, las ediciones sugeridas no son un medio de comunicación, si desea agregar un comentario o ampliar su pregunta, siéntase libre. –

+0

¿Cómo se obtiene el 1 de la matriz de bytes? Un 'int' es 4 bytes, que sería' {00, 00, 01, 00} ', que no es 1. – Amy

+0

Consulte mi 'respuesta'. Necesito más información. Conocer la matriz de bytes no es suficiente. ¿Cómo se ve la estructura nativa? – Amy

Respuesta

0

Esta no es una respuesta (todavía) pero es una pregunta/comentario con una cantidad considerable de código para comentarios. ¿Cómo interpretas tu matriz de bytes? Descomponerlo.

[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(); 
} 
3

Lo haría con un BinaryReader. Esto iría por estas líneas:

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

Tenga en cuenta que esto no funcionará directamente para el ejemplo de matriz de bytes que proporcionó. Los recuentos de caracteres y el campo ID no están en orden estándar little endian o bigendian. Podría ser que los campos sean de 16 bits y que estén antepuestos con campos de relleno de 16 bits. ¿Quién generó el presente bytestream?

Pero el formato exacto no es demasiado importante para esta estrategia, ya que solo puede cambiar ReadInt32 en ReadInt16, reordenarlos, lo que sea, para que funcionen.

No me gustan los atributos del serializador. Eso es porque acopla sus estructuras internas de datos a cómo se intercambia. Esto se rompe en caso de que necesite soportar múltiples versiones del formato de datos.

Cuestiones relacionadas