Lire le fichier binaire dans une structure

J'essaie de lire des données binaires en C

请先 登录 后评论

6 réponses

urini

Essayez ceci :

using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
    BinaryFormatter formatter = new BinaryFormatter();
    StructType aStruct = (StructType)formatter.Deserialize(filestream);
}
请先 登录 后评论
lubos hasko

Je ne vois aucun problème avec votre code.

juste hors de ma tête, et si vous essayez de le faire manuellement ? ça marche ?

BinaryReader reader = new BinaryReader(stream);
StructType o = new StructType();
o.FileDate = Encoding.ASCII.GetString(reader.ReadBytes(8));
o.FileTime = Encoding.ASCII.GetString(reader.ReadBytes(8));
...
...
...

essayez aussi

StructType o = new StructType();
byte[] buffer = new byte[Marshal.SizeOf(typeof(StructType))];
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(o, handle.AddrOfPinnedObject(), false);
handle.Free();

puis utilisez buffer[] dans votre BinaryReader au lieu de lire les données de FileStream pour voir si vous obtenez toujours l'exception AccessViolation.

Je n'ai pas eu de chance avec le BinaryFormatter, je suppose que je dois avoir une structure complète qui correspond exactement le contenu du fichier.

C'est logique, BinaryFormatter a son propre format de données, totalement incompatible avec le vôtre.

请先 登录 后评论
Robert Höglund

Je n'ai pas eu de chance avec BinaryFormatter, je suppose que je dois avoir une structure complète qui corresponde exactement au contenu du fichier. J'ai réalisé qu'en fin de compte, je n'étais pas intéressé par une grande partie du contenu du fichier de toute façon, alors j'ai opté pour la solution consistant à lire une partie du flux dans un bytebuffer, puis à le convertir à l'aide de

Encoding.ASCII.GetString()

pour les chaînes et

BitConverter.ToInt32()

pour les entiers.

Je devrai pouvoir analyser davantage le fichier plus tard, mais pour cette version, je me suis contenté de quelques lignes de code.

请先 登录 后评论
Ishmaeel

Le problème vient des chaînes dans votre structure. J'ai trouvé que le marshaling des types comme byte/short/int n'est pas un problème ; mais lorsque vous avez besoin de marshaler dans un type complexe tel qu'une chaîne, vous avez besoin de votre structure pour imiter explicitement un type non managé. Vous pouvez le faire avec l'attribut MarshalAs.

Pour votre exemple, ce qui suit devrait fonctionner :

[StructLayout(LayoutKind.Explicit)]
struct StructType
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string FileDate;

    [FieldOffset(8)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string FileTime;

    [FieldOffset(16)]
    public int Id1;

    [FieldOffset(20)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 66)] //Or however long Id2 is.
    public string Id2;
}
请先 登录 后评论
Ronnie

Lire directement dans les structures est mal - de nombreux programmes C ont échoué à cause de différents ordres d'octets, de différentes implémentations de compilateur de champs, de conditionnement, de taille de mot .......

Vous êtes le meilleur de la sérialisation et de la désérialisation octet par octet. Utilisez les éléments intégrés si vous le souhaitez ou familiarisez-vous simplement avec BinaryReader.

请先 登录 后评论
Community

Voici ce que j'utilise.
Cela a fonctionné avec succès pour moi pour lire le format exécutable portable.
C'est une fonction générique, donc T est votre Type struct.

public static T ByteToType<T>(BinaryReader reader)
{
    byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));

    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();

    return theStructure;
}
请先 登录 后评论
  • 19 abonnés
  • 0 favoris,451 Feuilleter
  • Robert Höglund posée à 2023-03-03 16:40