C# / .net中直接向结构体写入二进制数据的等效方法是什么?

3

结构体的确切结构并不重要。

据我所知,以下 C 代码正在读取“块”二进制数据(大小等于结构体大小),并直接将其写入结构体中(即前32字节到名称,下一个2字节到属性等)。C# 管理代码中是否有相应的等效方法?

请提供代码片段以展示类似的结果。为了节省时间,您可以简化为只有几个元素,并假设适当的文件流类型对象已经初始化。

注意:我将使用现有的遗留数据文件,因此现有数据文件的格式/打包方式很重要。例如,我不能仅使用 .net 序列化/反序列化,因为我将处理遗留现有文件(更改格式是不可行的)。

typedef struct _PDB 
{
   char name[32];
   unsigned short attrib;
   unsigned short version;
   unsigned int created;
   unsigned int modified;
   unsigned int backup;
   unsigned int modNum;
   unsigned int nextRecordListID;
   unsigned short numRecs;
} PDB;

void getFileType(FILE *in) 
{
   PDB p;
   fseek(in, 0, SEEK_SET);
   fread(&p, sizeof(p), 1, in);
. . .
}

你知道如果在不同字节序的机器之间共享文件,那段代码会出问题吗? - onemasse
我没有考虑过这一点,但对于这个应用程序来说,这不会成为问题(所有文件都是单一格式,由单一的遗留应用程序创建,并且在单一平台 - Windows XP上)。 - Gerald Davis
可能是A C# equivalent of C's fread file i/o的重复问题。 - Hans Passant
2个回答

7

我想你在询问StructLayoutAttributeFieldOffsetAttribute

以下是MSDN网站上的示例(摘录):

[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public class MySystemTime 
{
   [FieldOffset(0)]public ushort wYear; 
   [FieldOffset(2)]public ushort wMonth;
   [FieldOffset(4)]public ushort wDayOfWeek; 
   [FieldOffset(6)]public ushort wDay; 
   [FieldOffset(8)]public ushort wHour; 
   [FieldOffset(10)]public ushort wMinute; 
   [FieldOffset(12)]public ushort wSecond; 
   [FieldOffset(14)]public ushort wMilliseconds; 
}

好的,谢谢,到目前为止这部分很清晰。定义结构体的物理结构。那么现在如何直接写入结构体呢?相当于这个C语言代码行:"fread(&p, sizeof(p), 1, in)"。我只需要读取x个字节,然后将其强制转换为结构体吗? - Gerald Davis
1
你可以逐个字段地使用BitConverter.Toxxx方法,或者使用此方法。在性能方面可能没有太大的差异,但调试起来更容易。 - weismat
2
@theUnhandledException:C#确实支持联合(通过使用与myermian展示相同的代码重叠字段),因此您可以只需添加一个字节数组即可。 "正确"的方法可能是使用Marshal,但也可以使用BinaryFormatter来实现此目的。后者可能会添加元数据,因此您需要使用BinaryFormatter来读取它。Richard Taylor在这里解释了如何使用Marshal进行操作。 (http://geekswithblogs.net/taylorrich/archive/2006/08/21/88665.aspx) - Brian

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接