[英]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.