C#内存映射大文件并使用Marshal解析结构体信息
内存映射数据处理类主要函数及变量如下:
1 string _filepath; 2 /// <summary> 3 /// 引用内存映射文件 4 /// </summary> 5 private MemoryMappedFile _memoryFile = null; 6 /// <summary> 7 /// 用于访问内存映射文件的存取对象 8 /// </summary> 9 private MemoryMappedViewAccessor _accessor = null; 10 public ScientificData _ScientificData = new ScientificData(); 11 long _lenByte = 0; 12 public DatFileInfo(string filepath) 13 { 14 _filepath = filepath; 15 _memoryFile = MemoryMappedFile.CreateFromFile(_filepath); 16 _accessor = _memoryFile.CreateViewAccessor(); 17 // _stream = _memoryFile.CreateViewStream(); 18 FileInfo finfo = new FileInfo(filepath); 19 _lenByte = finfo.Length;//文件字节大小 20 } 21 public void SaveRawData(string savepath) 22 { 23 24 int currentByteNum = 0;//当前字节位置 25 uint ACountint = 0; 26 uint RCountint = 0; 27 ScientificData scientificData = new ScientificData(); 28 byte[] data = new byte[1036 * 1036]; 29 while (currentByteNum<= (_lenByte- 1036 * 1036)) 30 { 31 _accessor.Read<uint>(currentByteNum, out RCountint); 32 _accessor.Read<uint>(currentByteNum+4, out ACountint); 33 if (RCountint < 1400 && ACountint < 1401 && _accessor.ReadByte(currentByteNum+8)==0x0a && _accessor.ReadByte(currentByteNum + 9) == 0x0b)//初步判断条件,节省解析结构体时间 34 { 35 _accessor.ReadArray(currentByteNum, data, 0, data.Length);//读取结构体数据到字节数组 36 scientificData = ByteToStructure<ScientificData>(data);//字节数组解析到结构体 37 if((scientificData.aux_3a1 == 0x3A) && (scientificData.aux_3a3 == 0x3A))//进一步判断 38 { 39 ushort[,] sdata = scientificData.GetImageData();//得到所需的数据 40 saveRawData(savepath + ((int)((ACountint - 1)/15+1)).ToString()+ "_" + (ACountint-1).ToString() + "_"+ACountint + "_"+scientificData.aux_num + ".raw" , sdata); 41 currentByteNum += 1036 * 1036; 42 } 43 else 44 currentByteNum++; 45 } 46 else 47 currentByteNum++; 48 49 50 } 51 } 52 /// <summary> 53 /// 由byte数组转换为结构体 54 /// </summary> 55 public static T ByteToStructure<T>(byte[] dataBuffer) 56 { 57 object structure = null; 58 int size = Marshal.SizeOf(typeof(T)); 59 IntPtr allocIntPtr = Marshal.AllocHGlobal(size); 60 try 61 { 62 Marshal.Copy(dataBuffer, 0, allocIntPtr, size); 63 structure = Marshal.PtrToStructure(allocIntPtr, typeof(T)); 64 } 65 finally 66 { 67 Marshal.FreeHGlobal(allocIntPtr); 68 } 69 return (T)structure; 70 } 71 private void saveRawData(string savepath,ushort[,] data) 72 { 73 int len = data.Length*2; 74 byte[] bdata = new byte[len]; 75 Buffer.BlockCopy(data,0,bdata,0,len); 76 File.WriteAllBytes(savepath, bdata); 77 } 78 /// <summary> 79 /// 由结构体转换为byte数组 80 /// </summary> 81 public static byte[] StructureToByte<T>(T structure) 82 { 83 int size = Marshal.SizeOf(typeof(T)); 84 byte[] buffer = new byte[size]; 85 IntPtr bufferIntPtr = Marshal.AllocHGlobal(size); 86 try 87 { 88 Marshal.StructureToPtr(structure, bufferIntPtr, true); 89 Marshal.Copy(bufferIntPtr, buffer, 0, size); 90 } 91 finally 92 { 93 Marshal.FreeHGlobal(bufferIntPtr); 94 } 95 return buffer; 96 }
科学数据结构体定义如下:
//一幅1036*1036字节数据定义 public struct ScientificData { /参数信息 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] RelativePacketCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public Byte[] AbsolutePacketCount; ........ public byte aux_3a;//填充3A H ......... [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1036)] public OneImageRow[] ImageData;//图像数据行 /// <summary> /// 获取raw图数据 /// </summary> /// <returns>图像数据</returns> public ushort[,] GetImageData() { ushort[,] rawdata = new ushort[1036, 512]; for (int i = 0; i < 1036; i++) { var onerow = ImageData[i]; for (int j = 0; j < 512; j++) { rawdata[i, j] = (ushort)(((onerow.imagedata[j * 2] << 8) | onerow.imagedata[j * 2 + 1])) ; } } return rawdata; } }
图像数据结构体如下:
public struct OneImageRow { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] RelativePacketCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] AbsolutePacketCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] linehead;//行头 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] linenum;//行号 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public byte[] imagedata;//图像数据512×2=1024字节 public static string ByteToHex(byte[] bt) { var hex = BitConverter.ToString(bt, 0).ToUpper(); return hex; } }