AC#相当于C的fread文件I / O

任何人都可以告诉我如何在C#.NET版本2中直接获取一个字节数组结构? 就像C语言中熟悉的fread一样,到目前为止,我在读取字节stream和自动填充结构方面还没有取得太大的成功。 我已经看到一些使用unsafe关键字在托pipe代码中存在指针hocus-pocus的实现。

看看这个例子:

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

我有两个构造函数foobarStruct的原因

  • 是不是有一个空的构造函数。
  • 在实例化结构时将一块内存(作为字节数组)传入构造函数。

这个实现是否足够好,还是有一个更干净的方法来实现这一点?

编辑:我不想使用ISerializable接口或其实现。 我正在尝试读取一个二进制图像来解决使用的字段,并使用PE结构确定其数据。

使用P / Invoke编组没有任何问题,它不是不安全的,你不必使用unsafe关键字。 弄错它只会产生不好的数据。 比明确写入反序列化代码要容易得多,特别是当文件包含string时。 你不能使用BinaryReader.ReadString(),它假定该string是由BinaryWriter写的。 不过要确保你用一个struct声明来声明数据的结构,this.GetType()不太可能工作得很好。

下面是一个generics类,它将使它适用于任何结构声明:

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

文件中数据结构的示例声明:

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

您需要调整结构声明和属性才能与文件中的数据匹配。 读取文件的示例代码:

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

您可能想使用BinaryReader ,它允许您以二进制forms读取原始types。

byte[]创build一个MemoryStream ,然后使用BinaryReader 。 你应该能够读出结构并相应地填写你的对象。