我要将DataTable
保存到* .dbf文件(dBase IV)。所以我有这样的结构:
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct DbfHeader
{
[FieldOffset(0)]
private byte versionNumber;
[FieldOffset(1)]
private byte yearOfLastUpdate;
[FieldOffset(2)]
private byte monthOfLastUpdate;
[FieldOffset(3)]
private byte dayOfLastUpdate;
[FieldOffset(4)]
private Int32 numberOfRecords;
[FieldOffset(8)]
private Int16 lengthOfHeader;
[FieldOffset(10)]
private Int16 lengthOfEachRecord;
[FieldOffset(12)]
private Int16 reserved1;
[FieldOffset(14)]
private byte incompleteTransaction;
[FieldOffset(15)]
private byte encryptionFlag;
[FieldOffset(16)]
private byte[] freeRecordThread;
[FieldOffset(20)]
private byte[] reserved2;
[FieldOffset(28)]
private byte mdxFlag;
[FieldOffset(29)]
private byte languageDriver;
[FieldOffset(30)]
private Int16 reserved3;
public DbfHeader(int numberOfRecords, int numberOfFields, short recordLength, Encoding encoding)
{
// some code that initialize each field
}
}
另外,我有一种将DbfHeader
变量转换为byte[]
数组的方法,如下所示:
public static byte[] StructureToByteArray<T>(T structure)
{
int len = Marshal.SizeOf(structure);
byte[] result = new byte[len];
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.StructureToPtr(structure, ptr, true);
Marshal.Copy(ptr, result, 0, len);
Marshal.FreeHGlobal(ptr);
return result;
}
但这种方法不起作用。在Marshal.StructureToPtr(structure, ptr, true)
行,我得到了这个例外:
Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
任何人都知道出了什么问题?任何帮助将不胜感激。
答案 0 :(得分:3)
为什么您将fDeleteOld
传递给Marshal.StructureToPtr()
?
你应该尽可能地通过false
。
我认为你应该在复制内存后调用Marshal.DestroyStructure():
public static byte[] StructureToByteArray<T>(T structure)
{
int len = Marshal.SizeOf(structure);
byte[] result = new byte[len];
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.StructureToPtr(structure, ptr, false);
Marshal.Copy(ptr, result, 0, len);
Marshal.DestroyStructure(ptr, typeof(T));
Marshal.FreeHGlobal(ptr);
return result;
}
之前崩溃的原因是因为将fDeleteOld
传递为true假设您已经已经为该IntPtr调用了Marshal.StructureToPtr()
。因为你没有,它崩溃了(内存块没有按照StructureToPtr()期望的方式进行初始化。)
但是,您仍然需要按照上面的示例调用Marshal.DestroyStructure()
来清理内存。这是清理用于包含引用的结构的数据所必需的。 (您的特定示例结构不包含引用,但您可以将此类结构传递给StructureToByteArray()
)。
最后,请注意,如果你这样做,它就不会崩溃(除了演示如何使用fDeleteOld
标志外,这段代码没有意义):
Marshal.StructureToPtr(structure, ptr, false); // First time; must be false.
Marshal.StructureToPtr(structure, ptr, true); // Second time: Now it can be true.