C# 相当于 C 的 fread 文件 i/o
谁能告诉我如何在 C# .NET 版本 2 中以直接方式将字节数组放入结构中?就像 C 语言中熟悉的 fread
一样,到目前为止,我在读取字节流并自动填充结构方面还没有取得太大成功。我见过一些实现,其中通过使用 unsafe
关键字在托管代码中存在指针骗局。
看一下这个示例:
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 中有两个构造函数的原因
- 是不能有空构造函数。
- 实例化结构时,将内存块(作为字节数组)传递到构造函数中。
该实现是否足够好,或者是否有更简洁的方法来实现这一目标?
编辑:我不想使用 ISerialized 接口或其实现。 我正在尝试读取二进制图像来计算出所使用的字段并使用 PE 结构确定其数据。
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.
Have 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
- Is there cannot be an empty constructor.
- Pass in a block of memory (as a byte array) into the constructor when instantiating the structure.
Is that 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 work out the fields used and determine its data using the PE structures.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用 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:
A sample declaration for the structure of the data in the file:
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:
您可能想使用
BinaryReader
它允许您以二进制形式读取原始类型。创建
MemoryStream
从byte[]
中获取,然后使用其中的BinaryReader
。您应该能够读出结构并相应地填写您的对象。You probably want to use a
BinaryReader
which allows you to read in primitive types in binary form.Create a
MemoryStream
from thebyte[]
and then use theBinaryReader
from that. You should be able to read out the structure and fill in your object accordingly.