Para estructuras muy simples que no son serializables y contienen solo tipos de base, esto funciona. Lo uso para analizar archivos que tienen un formato conocido. Se eliminó la comprobación de errores para mayor claridad.
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;
}
}
}
Las estructuras deben ser declarados como esto (y no puede contener matrices, creo, no han intentado que fuera - el canje endian probablemente se confunden).
[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
Debería considerar hacer que su tipo sea serializable. Si eso es algo que le interesa, proporcionaré una muestra. Consulte "BinaryFormatter" para la serialización binaria. –
@Nate, gracias, parece que usar 'MemoryStream' es una buena idea! @GlennFerrieLive, nunca he trabajado con 'BinaryFormatter' antes, pero a juzgar por algunos ejemplos, me parece que se trata de" casting a struct ". Realmente apreciaré incluso una pequeña muestra. ¡Gracias! – Joulukuusi