Frage

Kann mir jemand sagen, wie ich in C# .NET Version 2 eine Reihe von Bytes in eine direkte Weise in eine Struktur bringen kann? Wie das Vertraute fread Wie in C gefunden, hatte ich bisher nicht viel Erfolg beim Lesen eines Stroms von Bytes und beim automatischen Füllen einer Struktur. Ich habe einige Implementierungen gesehen, bei denen im verwalteten Code Zeiger-Hocus-Pokus mithilfe des unsafe Stichwort.

Schauen Sie sich dieses Beispiel an:

public unsafe struct foobarStruct{

   /* fields here... */

   public foobarStruct(int nFakeArgs){
      /* Initialize the fields... */
   }

   public foobarStruct(byte[] data) : this(0) {
      unsafe {
         GCHandle hByteData = GCHandle.Alloc(data, GCHandleType.Pinned);
         IntPtr pByteData = hByteData.AddrOfPinnedObject();
         this = (foobarStruct)Marshal.PtrToStructure(pByteData, this.GetType());
         hByteData.Free();
      }
   }
}

Der Grund, warum ich zwei Konstrukteure habe foobarStruct

  • Gibt es keinen leeren Konstruktor?
  • In einen Speicherblock (als Byte -Array) in den Konstruktor geben, wenn die Struktur instanziiert.

Ist diese Implementierung gut genug oder gibt es eine viel sauberere Möglichkeit, dies zu erreichen?

Bearbeiten: Ich möchte die iserialisierbare Schnittstelle oder ihre Implementierung nicht verwenden. Ich versuche, ein binäres Bild zu lesen, um die verwendeten Felder zu erarbeiten und seine Daten mit den PE -Strukturen zu bestimmen.

War es hilfreich?

Lösung

Es ist nichts falsch daran, den P/Invoke Marshaller zu verwenden, es ist nicht unsicher und Sie müssen das unsichere Schlüsselwort nicht verwenden. Wenn Sie es falsch verstehen, werden nur schlechte Daten erzeugt. Es kann viel einfacher sein, den Deserialisierungscode explizit zu schreiben, insbesondere wenn die Datei Zeichenfolgen enthält. Sie können BinaryReader. Stellen Sie jedoch sicher, dass Sie die Struktur der Daten mit einer Strukturdeklaration deklarieren. GetType () funktioniert wahrscheinlich nicht gut.

Hier ist eine generische Klasse, die es für jede Strukturerklärung funktioniert:

  class StructureReader<T> where T : struct {
    private byte[] mBuffer;
    public StructureReader() {
      mBuffer = new byte[Marshal.SizeOf(typeof(T))];
    }
    public T Read(System.IO.FileStream fs) {
      int bytes = fs.Read(mBuffer, 0, mBuffer.Length);
      if (bytes == 0) throw new InvalidOperationException("End-of-file reached");
      if (bytes != mBuffer.Length) throw new ArgumentException("File contains bad data");
      T retval;
      GCHandle hdl = GCHandle.Alloc(mBuffer, GCHandleType.Pinned);
      try {
        retval = (T)Marshal.PtrToStructure(hdl.AddrOfPinnedObject(), typeof(T));
      }
      finally {
        hdl.Free();
      }
      return retval;
    }

Eine Beispielerklärung für die Struktur der Daten in der Datei:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct Sample {
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
  public string someString;
}

Sie müssen die Strukturdeklaration und die Attribute optimieren, um mit den Daten in der Datei übereinzustimmen. Beispielcode mit einer Datei:

  var data = new List<Sample>();
  var reader = new StructureReader<Sample>();
  using (var stream = new FileStream(@"c:\temp\test.bin", FileMode.Open, FileAccess.Read)) {
    while(stream.Position < stream.Length) {
      data.Add(reader.Read(stream));
    }
  }

Andere Tipps

Sie möchten wahrscheinlich a verwenden BinaryReader Dadurch können Sie in Binärform in primitiven Typen lesen.

Ein ... kreieren MemoryStream von dem byte[] und dann die benutze die BinaryReader davon. Sie sollten in der Lage sein, die Struktur auszulesen und Ihr Objekt entsprechend auszufüllen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top