这不是在C语言中声明结构体的方式。如果文件中的记录包含字符串,则可以类似地声明结构体:
struct Example {
int mumble;
char text[42];
};
相应的C#声明将如下所示:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
private struct Example {
public int mumble;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
public string text;
}
通常情况下,您可以使用BinaryReader读取数据。 但是它不能直接处理这样的字符串,您必须将它们作为byte[]读取并自己进行字符串转换。 您也无法利用声明性语法,您必须为结构体的每个成员编写一个调用。
有一个解决方法,Marshal类已经知道如何使用PtrToStructure()方法将非托管结构转换为托管结构。 这里有一个通用实现,它适用于任何可平移类型。 两个版本,一个静态版本从byte[]中读取,另一个实例方法被优化为重复从流中读取。 您可以使用FileStream或MemoryStream来实现。
using System;
using System.IO;
using System.Runtime.InteropServices;
class StructTranslator {
public static bool Read<T>(byte[] buffer, int index, ref T retval) {
if (index == buffer.Length) return false;
int size = Marshal.SizeOf(typeof(T));
if (index + size > buffer.Length) throw new IndexOutOfRangeException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
IntPtr addr = (IntPtr)((long)handle.AddrOfPinnedObject() + index);
retval = (T)Marshal.PtrToStructure(addr, typeof(T));
}
finally {
handle.Free();
}
return true;
}
public bool Read<T>(Stream stream, ref T retval) {
int size = Marshal.SizeOf(typeof(T));
if (buffer == null || size > buffer.Length) buffer = new byte[size];
int len = stream.Read(buffer, 0, size);
if (len == 0) return false;
if (len != size) throw new EndOfStreamException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
retval = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally {
handle.Free();
}
return true;
}
private byte[] buffer;
}
未经测试,希望它能正常工作。