与C的fread文件I / O等效的C# [英] A C# equivalent of C's fread file i/o

查看:169
本文介绍了与C的fread文件I / O等效的C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能告诉我如何在C#.NET版本2中以直接方式将字节数组放入结构中?就像在C中熟悉的 fread 一样,到目前为止,我在读取字节流并自动填充结构方面并没有取得太大的成功。我已经看到一些使用 unsafe 关键字在托管代码中存在指针轨迹的实现。

Can anyone tell me how to get a array of bytes into a structure in a direct fashion in C# .NET version 2? Like the familiar fread as found in C, so far I have not had much success in reading a stream of bytes and automatically filling a structure. I have seen some implementations where there is pointer hocus-pocus in the managed code by using the unsafe keyword.

看一下这个示例:

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

The reason I have two constructors in foobarStruct


  • 是否不能有空的构造函数。

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

是该实现足够好还是有更清洁的方法实现这一目标?

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

编辑:我不想使用ISerializable接口或它的实施。
我试图读取二进制图像以计算出使用的字段并使用PE结构确定其数据。

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

推荐答案

使用P / Invoke编组器没有任何问题,这也不是不安全的,而且您不必使用unsafe关键字。弄错它只会产生错误的数据。与显式编写反序列化代码相比,使用起来容易得多,尤其是当文件包含字符串时。您不能使用BinaryReader.ReadString(),它假定字符串是由BinaryWriter编写的。但是请确保使用结构体声明声明数据的结构,this.GetType()不太可能很好地工作。

There isn't anything wrong with using the P/Invoke marshaller, it is not unsafe and you don't have to use the unsafe keyword. Getting it wrong will just produce bad data. It can be a lot easier to use than explicitly writing the deserialization code, especially when the file contains strings. You can't use BinaryReader.ReadString(), it assumes that the string was written by BinaryWriter. Make sure however that you declare the structure of the data with a struct declaration, this.GetType() is not likely to work out well.

这里是一个通用类,它将使它适用于任何结构声明:

Here's a generic class that will make it work for any structure declaration:

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

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

A sample declaration for the structure of the data in the file:

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

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

You'll need to tweak the structure declaration and the attributes to get a match with the data in the file. Sample 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));
    }
  }

这篇关于与C的fread文件I / O等效的C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆