将二进制文件读入结构体 [英] Read binary file into a struct

查看:87
本文介绍了将二进制文件读入结构体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 C# 读取二进制数据.我在要阅读的文件中拥有有关数据布局的所有信息.我能够逐块"读取数据,即将前 40 个字节的数据转换为字符串,然后获取接下来的 40 个字节.

I'm trying to read binary data using C#. I have all the information about the layout of the data in the files I want to read. I'm able to read the data "chunk by chunk", i.e. getting the first 40 bytes of data converting it to a string, get the next 40 bytes.

由于数据至少有三个略有不同的版本,我想直接将数据读入结构体.感觉比逐行"阅读要正确得多.

Since there are at least three slightly different version of the data, I would like to read the data directly into a struct. It just feels so much more right than by reading it "line by line".

我尝试了以下方法但无济于事:

StructType aStruct;
int count = Marshal.SizeOf(typeof(StructType));
byte[] readBuffer = new byte[count];
BinaryReader reader = new BinaryReader(stream);
readBuffer = reader.ReadBytes(count);
GCHandle handle = GCHandle.Alloc(readBuffer, GCHandleType.Pinned);
aStruct = (StructType) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(StructType));
handle.Free();

流是一个打开的 FileStream,我从中开始读取.使用 Marshal.PtrToStructure 时,我得到一个 AccessViolationException.

The stream is an opened FileStream from which I have began to read from. I get an AccessViolationException when using Marshal.PtrToStructure.

由于我对文件末尾的数据不感兴趣,所以该流包含的信息比我试图读取的要多.

The stream contains more information than I'm trying to read since I'm not interested in data at the end of the file.

结构体定义如下:

[StructLayout(LayoutKind.Explicit)]
struct StructType
{
    [FieldOffset(0)]
    public string FileDate;
    [FieldOffset(8)]
    public string FileTime;
    [FieldOffset(16)]
    public int Id1;
    [FieldOffset(20)]
    public string Id2;
}

示例代码已从原始代码更改以缩短此问题的时间.

The examples code is changed from original to make this question shorter.

如何将文件中的二进制数据读入结构体?

How would I read binary data from a file into a struct?

推荐答案

问题在于结构中的 string.我发现像 byte/short/int 这样的编组类型不是问题;但是当您需要编组为复杂类型(例如字符串)时,您需要您的结构显式模拟非托管类型.您可以使用 MarshalAs 属性执行此操作.

The problem is the strings in your struct. I found that marshaling types like byte/short/int is not a problem; but when you need to marshal into a complex type such as a string, you need your struct to explicitly mimic an unmanaged type. You can do this with the MarshalAs attrib.

对于您的示例,以下应该有效:

For your example, the following should work:

[StructLayout(LayoutKind.Explicit)]
struct StructType
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string FileDate;

    [FieldOffset(8)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string FileTime;

    [FieldOffset(16)]
    public int Id1;

    [FieldOffset(20)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 66)] //Or however long Id2 is.
    public string Id2;
}

这篇关于将二进制文件读入结构体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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