对于不是可串行化且仅包含基本类型的非常简单的结构体,这可行。我用它来解析具有已知格式的文件。清除错误检查已删除。
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
namespace FontUtil
{
public static class Reader
{
public static T Read<T>(BinaryReader reader, bool fileIsLittleEndian = false)
{
Type type = typeof(T);
int size = Marshal.SizeOf(type);
byte[] buffer = new byte[size];
reader.Read(buffer, 0, size);
if (BitConverter.IsLittleEndian != fileIsLittleEndian)
{
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo field in fields)
{
int offset = (int)Marshal.OffsetOf(type, field.Name);
int fieldSize = Marshal.SizeOf(field.FieldType);
for (int b = offset, t = fieldSize + b - 1; b < t; ++b, --t)
{
byte temp = buffer[t];
buffer[t] = buffer[b];
buffer[b] = temp;
}
}
}
GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);
T obj = (T)Marshal.PtrToStructure(h.AddrOfPinnedObject(), type);
h.Free();
return obj;
}
}
}
的Structs需要声明是这样的(并且不能包含数组,我认为,并没有说出来 - 字节序交换可能会感到困惑)。
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct NameRecord
{
public UInt16 uPlatformID;
public UInt16 uEncodingID;
public UInt16 uLanguageID;
public UInt16 uNameID;
public UInt16 uStringLength;
public UInt16 uStringOffset; //from start of storage area
}
'MemoryStream'? – Nate
你应该考虑让你的类型可序列化。如果这是你感兴趣的东西,我会提供一个样本。有关二进制序列化,请参阅“BinaryFormatter”。 –
@Nate,谢谢,它似乎使用'MemoryStream'是一个好主意! @GlennFerrieLive,我以前从来没有使用过'BinaryFormatter',但是通过一些例子来判断它看起来像是“为我铸造一个结构体”。即使是一个小样本,我也会很感激。谢谢! – Joulukuusi