C#,从二进制文件中读取结构

B_o*_*old 6 c# binary structure file

我想从二进制文件中读取结构.在C++中,我会这样做:

stream.read((char*)&someStruct, sizeof(someStruct));
Run Code Online (Sandbox Code Playgroud)

在C#中是否有类似的方式?BinaryReader仅适用于内置类型.在.NET 4中有一个MemoryMappedViewAccessor.它提供了Read<T>似乎是我想要的方法,除了我手动必须跟踪我想要读取的文件中的位置.有没有更好的办法?

Jes*_*det 13

public static class StreamExtensions
{
    public static T ReadStruct<T>(this Stream stream) where T : struct
    {
        var sz = Marshal.SizeOf(typeof(T));
        var buffer = new byte[sz];
        stream.Read(buffer, 0, sz);
        var pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        var structure = (T) Marshal.PtrToStructure(
            pinnedBuffer.AddrOfPinnedObject(), typeof(T));
        pinnedBuffer.Free();
        return structure;
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要确保使用[StructLayout]和可能的[FieldOffset]注释声明结构以匹配文件中的二进制布局

编辑:

用法:

SomeStruct s = stream.ReadStruct<SomeStruct>();
Run Code Online (Sandbox Code Playgroud)

  • 但是如果你用它来解析一个文件格式,其中大部分都是简单类型的标题块那么它是非常可行的 (2认同)

Guf*_*ffa 2

在 C# 中可以执行类似的操作,但随后您必须将大量属性应用于结构,以便准确控制它在内存中的布局方式。默认情况下,JIT 编译器控制结构成员在内存中的布局方式,这通常意味着考虑到速度和内存使用情况,它们会被重新排列和填充,以获得最有效的布局。

最简单的方法通常是使用 BinaryReader 读取文件中结构的单独成员,并将值放入类的属性中,即手动将数据反序列化到类实例中。

通常,读取文件是此操作的瓶颈,因此读取单独成员的小开销不会明显影响性能。