2011-01-30 18 views
8

Ottengo una matrice di byte, ho bisogno di unmarshal su C# struct. Conosco il tipo di struct, ha alcuni campi di stringhe. Le stringhe nell'array di byte appaiono così: due primi byte sono la lunghezza della stringa, quindi la stringa stessa. Non conosco la lunghezza delle corde. Lo so che è Unicode!Come eseguire il marshalling di strutture con campi di stringa di lunghezza sconosciuta in 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 
} 

l'array di byte si presenta in questo modo: 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,

ho trovato anche questo link con lo stesso problema irrisolto: loading binary data into a structure

Grazie a tutti, Ofir

+0

Ofir, le modifiche suggerite non sono intese come mezzo di comunicazione, se si desidera aggiungere un commento o espandere la domanda sentirsi libero. –

+0

Come si ottiene 1 dall'array di byte? Un 'int' è 4 byte, che sarebbe' {00, 00, 01, 00} ', che non è 1. – Amy

+0

Si prega di consultare la mia 'risposta'. Ho bisogno di più informazioni Conoscere l'array di byte non è abbastanza. Come si presenta la struttura nativa? – Amy

risposta

0

Questa non è una risposta (ancora) ma è una domanda/commento con una quantità considerevole di codice per il feedback. Come interpreti il ​​tuo array di byte? Scomposizione.

[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 farei con un BinaryReader. Questo andrebbe in questo modo:

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

Si noti che questo non funzionerà direttamente per l'esempio di array di byte fornito. Il conteggio dei caratteri e il campo ID non sono in standard little endian o bigendiano. Potrebbe essere che i campi siano a 16 bit e che siano anteponenti con campi di riempimento a 16 bit. Chi ha generato questo filmato?

Tuttavia, il formato esatto non è troppo importante per questa strategia, in quanto è possibile modificare lo ReadInt32 in ReadInt16, riordinarlo, qualunque sia, per farlo funzionare.

Non sono interessato agli attributi del serializzatore. Questo perché collega le strutture dati interne a come viene scambiato. Questo si interrompe nel caso in cui sia necessario supportare più versioni del dataformat.

Problemi correlati