C # equivalent to C fread file i / o

Can someone tell me how to get an array of bytes into a structure directly in C # .NET version 2? Like the familiar fread found in C, so far I have not had much success in reading the byte stream and automatically populating the structure. I saw some implementations where the managed code has a hocus-pocus pointer using the unsafe keyword.

Take a look at this sample:

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

The reason I have two constructors in foobarStruct

  • Cannot be an empty constructor.
  • Pass in a block of memory (as an array of bytes) to the constructor when creating an instance of the structure.

Is this implementation good enough or is there a much cleaner way to achieve this?

Edit: I do not want to use the ISerializable interface or its implementation. I am trying to read a binary image to process used fields and determine its data using PE structures.

+7
c # fread
source share
2 answers

There is nothing wrong with using the P / Invoke marshaller, it is unsafe, and you do not need to use the unsafe keyword. If you are mistaken, this will lead to bad data. It can be a lot easier to use than explicitly writing deserialization code, especially when the file contains lines. You cannot use BinaryReader.ReadString (), it assumes the string was written by BinaryWriter. However, make sure you declare the data structure with a struct declaration. This.GetType () is unlikely to work well.

Here is a generic class that will make it work to declare any structure:

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

An example declaration for the data structure in a file:

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

You will need to configure the declaration of the structure and attributes in order to match the data in the file. Example code that reads a file:

  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)); } } 
+10
source share

You might want to use BinaryReader , which allows you to read primitive types in binary form.

Create a MemoryStream from byte[] , and then use the BinaryReader . You should be able to read the structure and fill out your object accordingly.

+2
source share

All Articles