2009-12-11 5 views
2

Je suis coincé sur celui-ci.Lecture de données binaires en utilisant MarshalAs et StructLayout

Je lis un fichier binaire qui a te format suivant:

Field name Size in bytes  Example 
------------------------------------- 
Date  19    1998_12_22 PM 20:15 
Serial  4     0001 

Utilisation de la struct suivante et en utilisant les réponses à this question je suis en train de lire le fichier.

[StructLayout(LayoutKind.Explicit, Size=23, Pack = 1)] 
struct MeasurementStruct 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)] 
    [FieldOffset(0)] 
    public string Date; 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] 
    [FieldOffset(19)] 
    public string Serial; 
} 

Cependant, lors de l'instanciation de la classe qui détient ce struct je reçois une erreur à FieldOffset 19. Malheureusement, cette erreur est en néerlandais mais il signifie à peu près « Impossible de charger MeasurementStruct parce que le champ à la sortie 19 est pas bien aligné (les champs peuvent se chevaucher) ".

J'ai découvert que la modification du FieldOffset [19] à FieldOffset [20] fait disparaître l'erreur. Cependant, 20 n'est pas le bon décalage dans mon cas, n'est-ce pas?

Répondre

1

Il semble qu'il y ait un problème de taille entre vos données (23 octets) et la taille de la structure (24 octets). Est-ce normal ? Mise à jour: L'attribut Pack = 1 devrait garantir l'alignement de la mémoire, mais googling donne une réponse divergente sur l'alignement du champ de la structure . Ce que vous pouvez faire est de lire 23 octets dans un tableau d'octets, puis extraire les deux chaînes avec la classe de codage:

byte[] array = ... // read 23 bytes 
String s1 = Encoding.ASCII.GetString(array, 0, 19); 
String s2 = Encoding.ASCII.GetString(array, 19, 4); 
+0

c'est une faute de frappe! Fixe .. –

+0

merci pour votre réponse. la structure que j'ai donnée était juste une version simplifiée du format de fichier. Le format réel est beaucoup plus grand et complexe, donc encoder tous les champs un par un n'est pas vraiment une option –

0

20 est probablement le bon décalage pour cette architecture. Le compilateur remplira avec des zéros pour mettre les membres struct sur des emplacements pairs. Exactement "comment même" est l'architecture et le compilateur en fonction, mais il doit être un multiple de 4 dans les architectures 32 bits si je ne me trompe pas.

Par exemple, la struct suivante:

struct MyStruct 
{ 
    char ch; // Offset 0 
      // 3 "invisible" bytes padding inserted by the compiler 
    int i; // Offset 4 
} 
0

Peut-être que string nécessite 2 octets par caractère (unicode), se lisent comme un tableau d'octets et utiliser ASCIIEncoding pour convertir en chaîne

0

Aucun des réponses où exactement ce que je cherche, mais j'ai trouvé une meilleure approche moi-même en définissant la structure suit.

[StructLayout(LayoutKind.Sequential, Size = MeasurementStructSize, Pack = 1)] 
struct MeasurementStruct 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)] 
    public string Date; 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] 
    public string SerialNumber; 

} 

J'ai modifié LayoutKind en séquence. Dans ce cas, le champ Pack a en réalité une signification et je n'ai pas besoin d'ajouter les FieldOffsets. Ce qui précède fonctionne bien.

Merci quand même à vous tous!

Questions connexes