Answer-ID
  • Întrebări
  • Tag-uri
  • Categorii
Notificări
Recompense
Înregistrare
După înregistrare, veți primi notificări despre răspunsurile și comentariile la întrebările DVS.
Logare
Dacă aveţi deja un cont, autentificaţi-vă pentru a verifica notificările noi.
Aici vor fi recompensele pentru întrebările, răspunsurile și comentariile adăugate sau modificate.
Mai mult
Sursă
Editează
Robert Höglund
Robert Höglund

Citiți fișierul binar într-un struct

Încerc să citesc datele binare folosind C #. Am toate informațiile despre aspectul datelor din fișierele pe care vreau să le citesc. Sunt capabil să citesc datele "bucată pe bucată", adică să primesc primele 40 octeți de date care o convertesc într-un șir, să obțin următoarele 40 de octeți.

Întrucât există cel puțin trei versiuni ușor diferite ale datelor, aș dori să citesc datele direct într-un struct. Simt doar mult mai mult decât căutând-o "pe linie".

Am încercat următoarea abordare, dar fără nici un folos:

StructType aStruct;
int count = Marshal.SizeOf(typeof(StructType));
byte[] readBuffer = new byte[count];
BinaryReader reader = new BinaryReader(stream);
readBuffer = reader.ReadBytes(count);
GCHandle handle = GCHandle.Alloc(readBuffer, GCHandleType.Pinned);
aStruct = (StructType) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(StructType));
handle.Free();

Fluxul este un FileStream deschis de la care am început să citesc. Obțineți un AccessViolationExceptio n când utilizați Marshal.PtrToStructure .

Fluxul conține mai multe informații decât încerc să citesc deoarece nu mă interesează datele de la sfârșitul fișierului.

Structura este definită ca:

[StructLayout(LayoutKind.Explicit)]
struct StructType
{
    [FieldOffset(0)]
    public string FileDate;
    [FieldOffset(8)]
    public string FileTime;
    [FieldOffset(16)]
    public int Id1;
    [FieldOffset(20)]
    public string Id2;
}

Codul de exemple este modificat de la original pentru a face această întrebare mai scurtă.

Cum aș citi datele binare dintr-un fișier într-un struct?

52 2008-08-05T14:28:57+00:00 6
Programare
struct
c#
io
binaryfiles
Comentarii la întrebare (0)
urini
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#2436

Incearca asta:

using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
    BinaryFormatter formatter = new BinaryFormatter();
    StructType aStruct = (StructType)formatter.Deserialize(filestream);
}
0
0
Comentarii (0)
lubos hasko
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#2474

Nu văd nici o problemă cu codul tău.

doar din cap, dar dacă încerci să o faci manual? funcționează?

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));
...
...
...

încercați, de asemenea

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();

apoi utilizați tampon [] în BinaryReader în loc să citiți date din FileStream pentru a vedea dacă totuși obțineți excepția AccessViolation.

Nu am avut noroc folosind   BinaryFormatter, cred că trebuie   aveți un struct complet care se potrivește   exact conținutul fișierului.

Asta are sens, BinaryFormatter are propriul format de date, complet incompatibil cu a ta.

0
0
Comentarii (0)
Robert Höglund
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#3200

Nu am avut noroc folosind BinaryFormatter, cred că trebuie să am o structură completă care să se potrivească exact cu conținutul fișierului. Mi-am dat seama că, în cele din urmă, nu m-am interesat prea mult de conținutul fișierului, așa că am mers cu soluția de a citi o parte a fluxului într-un bytebuffer și apoi să îl convertesc folosind

Encoding.ASCII.GetString()

pentru șiruri de caractere și

BitConverter.ToInt32()

pentru numere întregi.

Va trebui să fiu capabil să analizez mai mult fișierul mai târziu, dar pentru această versiune am scăpat cu doar câteva linii de cod.

0
0
Comentarii (0)
Ishmaeel
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#20803

Problema este șirul s din structura dvs. Am constatat că tipurile de marshaling cum ar fi byte / short / int nu reprezintă o problemă; dar atunci când aveți nevoie să marshal într-un tip complex, cum ar fi un șir, aveți nevoie de struct dumneavoastră pentru a imita în mod explicit un tip neangajat. Poți să faci asta cu atributul Marshal.

Pentru exemplul dvs., ar trebui să funcționeze următoarele:

[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;
}
0
0
Comentarii (0)
Ronnie
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#124089

Citirea direct în structuri este rău - multe dintre programele C au căzut din cauza ordinelor diferite de octeți, implementări diferite de compilatoare ale câmpurilor, ambalare, dimensiune de cuvânt .......

Ești cel mai bun de a serializa și de a descoperi byte prin byte. Utilizați build-ul în chestii dacă doriți sau pur și simplu să vă obișnuiți cu BinaryReader.

0
0
Comentarii (0)
nevelis
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#2777781

După cum a spus Ronnie, aș folosi BinaryReader și citesc fiecare câmp individual. Nu găsesc linkul la articol cu ​​această informație, dar sa observat că folosirea lui BinaryReader pentru citirea fiecărui câmp individual poate fi mai rapid decât Marshal.PtrToStruct, dacă structul conține mai puțin de 30-40 de câmpuri. Voi posta linkul la articol când îl găsesc.

The article's link is at: http://www.codeproject.com/Articles/10750/Fast-Binary-File-Reading-with-C

Atunci când marshaling o serie de structuri, PtrToStruct câștigă mai repede de mâna superioară, pentru că vă puteți gândi la numărul de câmp ca câmp * lungime matrice.

0
0
Comentarii (0)
Utilizator anonim
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#4074557

Iată ce folosesc.
Acest lucru a funcționat cu succes pentru citirea formatului portabil executabil.
Este o funcție generică, deci T este struct .

public static T ByteToType(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;
}
0
0
Comentarii (0)
Adăugati o întrebare
Categorii
Toate
Tehnologii
Cultură
Viață / Artă
Stiință
Profesii
Afaceri
ID
KO
RU
© Answer-ID 2021
Sursă
stackoverflow.com
în cadrul licenței cc by-sa 3.0 cu atribuire