一晃又好长时间没写博客了,今天总结一下近期的收获。
在做项目的时候需要用C#读取一个二进制文件。先说一下这个文件是怎么存的?文件的内容是有c++种的结构体存入的,因此,我们在读文件的时候需要将其解析成结构体,然后在进行读取。
结构体如下:
[StructLayout(LayoutKind.Sequential, Pack = 1)] //c#中数组长度与c中相同
public struct JOBStepTemplate_Head //c中该结构体长度为20,c#中为32
{
public char IN_CASS;
public char OUT_CASS;
public char START_SLOT;
public char END_SLOT;
public int METHOD_COUNT;
public char EDIT_TYPE;
public char PROGRESS;
public char DIRECTORY_TYPE;
public long DIRECTORY_DATE;
public char STATUS_SAVE;
}
在解析上面结构体时,我们发现c#中的结构体和c中的结构体长度不一样,因此加入
[StructLayout(LayoutKind.Sequential, Pack = 1)],这句话保证了c#和c的结构体是等长的。
FileStream fs;
BinaryReader br;
string filename = @"D:\Project\jobhistroy\CTC\Scheduler\lotlog\Job_list.dat"; //路径
if (!File.Exists(filename))
{
MessageBox.Show("Job_list文件不存在", "提示", MessageBoxButtons.YesNoCancel);
}
fs = new FileStream(filename, FileMode.Open); //获取流对象
br = new BinaryReader(fs); //二进制读取
br.Read(buffer, 0, 14); //读取头
上面这段代码是保存路径,以及创建流对象。因为项目中二进制文件会有一个头,长度为14,因此,最后一行将头读取。这个可以用来做判断,也就是说,如果有多个类似的二进制文件的话,可以用这个头来进行区分。
byte[] JOB_DATA = new byte[size]; //存放工作数据
br.Read(JOB_DATA, 0, size);
// ===================================================将内容读取到byte数组中
IntPtr structPtr = Marshal.AllocHGlobal(size); //分配结构体大小的内存空间
Marshal.Copy(JOB_DATA, 0, structPtr, size); //将byte数组拷到分配好的内存空间
JOBS_Head[JOBCOUNT] = (JOBStepTemplate_Head)Marshal.PtrToStructure(structPtr, typeof(JOBStepTemplate_Head)); //将内存空间转换为目标结构体
Marshal.FreeHGlobal(structPtr); //释放内存空间
//====================================================
上面代码中,size是结构体的长度
JOBStepTemplate_Head job = new JOBStepTemplate_Head();
int size = Marshal.SizeOf(job);
这样就搞定了。JOB_DATA是一个二进制数组,用来保存从文件中读出的size个字节。下面是将读出的size个字节转换成结构体。
从二进制文件读数据到结构体应该就这些,没有什么。由于项目原因,代码不好全不粘贴上,只写部分核心代码。