[英]C#, read structures from binary file
我想从二进制文件中读取结构。 在C ++中,我会这样做:
stream.read((char*)&someStruct, sizeof(someStruct));
在C#中是否有类似的方式? BinaryReader仅适用于内置类型。 在.NET 4中有一个MemoryMappedViewAccessor。 它提供了类似Read<T>
,这似乎是我想要的,除了我手动必须跟踪我想要读取的文件中的位置。 有没有更好的办法?
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;
}
}
您需要确保使用[StructLayout]和可能的[FieldOffset]注释声明结构以匹配文件中的二进制布局
编辑:
用法:
SomeStruct s = stream.ReadStruct<SomeStruct>();
这是Jesper代码的略微修改版本:
public static T? ReadStructure<T>(this Stream stream) where T : struct
{
if (stream == null)
return null;
int size = Marshal.SizeOf(typeof(T));
byte[] bytes = new byte[size];
if (stream.Read(bytes, 0, size) != size) // can't build this structure!
return null;
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
}
它成功处理EOF案例,因为它返回一个可空类型。
可以在C#中执行类似的操作,但是您必须将大量属性应用于结构,以便您可以精确控制它在内存中的布局方式。 默认情况下,JIT编译器控制结构成员在内存中的布局方式,这通常意味着考虑到速度和内存使用情况,它们会重新排列并填充以实现最高效的布局。
最简单的方法通常是使用BinaryReader读取文件中结构的单独成员,并将值放在类的属性中,即手动将数据反序列化为类实例。
通常它正在读取此操作中的瓶颈文件,因此读取单独成员的小开销不会显着影响性能。
C#中没有类似的方法。 此外,由于其不可移植性,这是不推荐的序列化方式。 请改用http://www.codeproject.com/KB/cs/objserial.aspx 。
只是详细说明Guffa和jesperll的答案,这里是一个使用基本相同的ReadStruct
方法(仅作为扩展方法)读取ASF(WMV / WMA)文件的文件头中的示例
MemoryStream ms = new MemoryStream(headerData);
AsfFileHeader asfFileHeader = ReadStruct<AsfFileHeader>(ms);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
internal struct AsfFileHeader
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] object_id;
public UInt64 object_size;
public UInt32 header_object_count;
public byte r1;
public byte r2;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.