using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SERVER { /// /// Hex文件处理 /// public class HexFile { /// 加载文件大小 private const int _loadFileSize = 1024 * 1024 * 2; /// 加载数据大小 private const int _loadDataSize = 1024 * 1024 * 2; /// 加载Hex文件数据 private byte[] _LoadHexFileData = new byte[_loadFileSize]; /// 加载数据Buff private byte[] _LoadDataBuff = new byte[_loadDataSize]; /// 加载结束地址 private int _LoadEndAddr; /// C1-Hex文件起始值 private int _HexStart_C1 = 0; /// 解析出的文件数据 private byte[] _ParseData; /// 解析出的配置数据 private byte[] _ParseConfigData; /// 匹配起始值 private int _matchingValue; private readonly int _matchingAddr = 49152; //0xC000 匹配数据起始地址 /// 匹配数据 private byte[] _matchingData = new byte[512]; /// /// 解析Hex文件 /// /// public byte[] DealHexFile(Stream filePath) { bool tmpRet = LoadDataFromFile(filePath); byte[] checkSum = new byte[4]; int tmpIdx = 0; int tmpLineCnt = 1; int tmpHexValidLenght = _LoadEndAddr - _HexStart_C1; if (tmpRet) { StringBuilder parse = new StringBuilder(); //Dim tmpStrBuffer As String for (tmpIdx = _HexStart_C1; tmpIdx < _LoadEndAddr; tmpIdx++) { parse.Append(HexByteStr(_LoadDataBuff[tmpIdx])); //<10ms } _ParseData = ConvertHexStringToBytes(parse.ToString()); Array.Copy(_ParseData, _matchingValue, _matchingData, 0, _matchingData.Length); //Console.WriteLine($"——解析匹配数据——:{vbCrLf}{BitConverter.ToString(_matchingData)}") //'Dim a() As Byte = {&H0} //'Dim b As String = Encoding.GetEncoding("GBK").GetString(a) ////_matchingData //byte[] project = new byte[2]; //项目编码 2 Bytes //Array.Copy(_matchingData, 0, project, 0, project.Length); ////Dim projects As String = Encoding.GetEncoding("GBK").GetString(project) //string projects = $"{project[0] + project[1] * 256}"; //projects = projects.Replace("\0", ""); //byte[] roomId = new byte[4]; //房型Id 4 Bytes //Array.Copy(_matchingData, project.Length, roomId, 0, roomId.Length); ////Dim roomIds As String = Encoding.GetEncoding("GBK").GetString(roomId) //string roomIds = $"{BitConverter.ToUInt32(roomId, 0)}"; //roomIds = roomIds.Replace("\0", ""); //byte[] version = new byte[20]; //版本号 20 Bytes //Array.Copy(_matchingData, (project.Length + roomId.Length), version, 0, version.Length); //string versions = Encoding.GetEncoding("GBK").GetString(version); //versions = versions.Replace("\0", ""); //byte[] mcu = new byte[16]; //MCU型号 16 Bytes //Array.Copy(_matchingData, (project.Length + roomId.Length + version.Length), mcu, 0, mcu.Length); //string mcus = Encoding.GetEncoding("GBK").GetString(mcu); //mcus = mcus.Replace("\0", ""); //byte[] central = new byte[16]; //中控型号 16 Bytes //Array.Copy(_matchingData, (project.Length + roomId.Length + version.Length + mcu.Length), central, 0, central.Length); //string centrals = Encoding.GetEncoding("GBK").GetString(central); //centrals = centrals.Replace("\0", ""); //byte[] remark = new byte[64]; //备注 64 Bytes //Array.Copy(_matchingData, (project.Length + roomId.Length + version.Length + mcu.Length + central.Length), remark, 0, remark.Length); // string remarks = Encoding.GetEncoding("GBK").GetString(remark); //remarks = remarks.Replace("\0", ""); ////MatchingInfo(projects, roomIds, versions, mcus, centrals, remarks); } return _ParseData; } public string Get_HexStart_C1() { return HexStringToBytes(_HexStart_C1); } /// /// 获取Hex文件中信息 /// /// public string GetHexInfo() { //_matchingData byte[] project = new byte[2]; //项目编码 2 Bytes Array.Copy(_matchingData, 0, project, 0, project.Length); //Dim projects As String = Encoding.GetEncoding("GBK").GetString(project) string projects = $"{project[0] + project[1] * 256}"; projects = projects.Replace("\0", ""); byte[] roomId = new byte[4]; //房型Id 4 Bytes Array.Copy(_matchingData, project.Length, roomId, 0, roomId.Length); //Dim roomIds As String = Encoding.GetEncoding("GBK").GetString(roomId) string roomIds = $"{BitConverter.ToUInt32(roomId, 0)}"; roomIds = roomIds.Replace("\0", ""); byte[] version = new byte[20]; //版本号 20 Bytes Array.Copy(_matchingData, (project.Length + roomId.Length), version, 0, version.Length); string versions = Encoding.GetEncoding("GBK").GetString(version); versions = versions.Replace("\0", ""); byte[] mcu = new byte[16]; //MCU型号 16 Bytes Array.Copy(_matchingData, (project.Length + roomId.Length + version.Length), mcu, 0, mcu.Length); string mcus = Encoding.GetEncoding("GBK").GetString(mcu); mcus = mcus.Replace("\0", ""); byte[] central = new byte[16]; //中控型号 16 Bytes Array.Copy(_matchingData, (project.Length + roomId.Length + version.Length + mcu.Length), central, 0, central.Length); string centrals = Encoding.GetEncoding("GBK").GetString(central); centrals = centrals.Replace("\0", ""); byte[] remark = new byte[64]; //备注 64 Bytes Array.Copy(_matchingData, (project.Length + roomId.Length + version.Length + mcu.Length + central.Length), remark, 0, remark.Length); string remarks = Encoding.GetEncoding("GBK").GetString(remark); remarks = remarks.Replace("\0", ""); return centrals; } /// /// 加载hex文件数据 /// /// /// private bool LoadDataFromFile(Stream path) { Array.Clear(_LoadHexFileData, 0, _LoadHexFileData.Length); try { //System.IO.Stream fs = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read); if (path.Length <= _loadFileSize) { path.Read(_LoadHexFileData, 0, (int)path.Length); } else { return false; } path.Close(); } catch (Exception ex) { return false; } return HexFileToData(_LoadHexFileData, _LoadDataBuff, ref _LoadEndAddr); } private string HexByteStr(byte hexByte) { if (hexByte < 16) { return "0" + Convert.ToString(hexByte, 16).ToUpper(); } else { return Convert.ToString(hexByte, 16).ToUpper(); } } /// /// 解析Hex文件到Byte数组 /// /// /// /// /// private bool HexFileToData(byte[] hexBuffer, byte[] dataBuffer, ref int endAddr) { int i = 0; //行数 int LineCnt = 0; int DataType_00_Idx = 0; //清空数据缓存区域 for (i = 0; i < dataBuffer.Length; i++) { dataBuffer[i] = 0xFF; } //本行数据缓存 byte[] dataStrBuf = new byte[32]; byte[] dataValBuf = new byte[16]; //首地址标记 bool headAddrFlag = true; //本行地址值 int tmpLineAdd = 0; //偏移地址 0x04 数据类型指示偏移地址 int LineAddOffestBase = 0; //结束地址 endAddr = 0; byte[] flashAddressBuf = new byte[4]; int flashAddress = 0; //INSTANT C# NOTE: The ending condition of VB 'For' loops is tested only on entry to the loop. Instant C# has created a temporary variable in order to use the initial value of hexBuffer.Length for every iteration: int tempVar = hexBuffer.Length; for (i = 0; i < tempVar; i++) { //首先找到冒号 if (hexBuffer[i] == 0x3A) //&H3A = ":" { LineCnt += 1; //B0:数据长度 int dataLen = (StrToHex(hexBuffer[i + 1]) * 16 + StrToHex(hexBuffer[i + 2])); if (dataLen > 0) { //By:CheckSum byte checkSum = (byte)(StrToHex(hexBuffer[i + 9 + dataLen * 2]) * 16 + StrToHex(hexBuffer[i + 10 + dataLen * 2])); //取出整行数据 byte[] rowDataStrBuf = new byte[42]; byte[] rowDataValBuf = new byte[21]; int rowLen = 0; Array.Clear(rowDataStrBuf, 0, 42); Array.Clear(rowDataValBuf, 0, 21); rowLen = (dataLen * 2) + 10; Array.Copy(hexBuffer, i + 1, rowDataStrBuf, 0, rowLen); StrToHex(rowDataValBuf, rowDataStrBuf, Convert.ToUInt16(rowLen / 2.0)); //using System; int tempVar2 = Convert.ToInt32(rowLen / 2.0); byte tempCheckSum = GetSumChecks(rowDataValBuf, ref tempVar2); if (tempCheckSum != 0xFF) { return false; //CheckSum校验不通过,返回错误 } //B4~Bx:数据内容 Array.Clear(dataStrBuf, 0, 32); Array.Clear(dataValBuf, 0, 16); Array.Copy(hexBuffer, i + 9, dataStrBuf, 0, dataLen * 2); StrToHex(dataValBuf, dataStrBuf, (UInt16)dataLen); } //B1~B2:取出地址位的值 Array.Copy(hexBuffer, i + 3, flashAddressBuf, 0, 4); //本行地址取出来放在 flashAddress中’ UInt16 tempVar3 = (UInt16)tmpLineAdd; StrToHex(ref tempVar3, flashAddressBuf); tmpLineAdd = tempVar3; flashAddress = LineAddOffestBase + tmpLineAdd; //B3:数据类型 var dataType = StrToHex(hexBuffer[i + 8]); switch (dataType) { case 0: //数据记录 DataType_00_Idx = DataType_00_Idx + 1; //将第一个00类型数据的地址作为起始地址, 保存到 _HexStart_C1 if (DataType_00_Idx == 1) { _HexStart_C1 = flashAddress; _matchingValue = _matchingAddr - _HexStart_C1; } Array.Copy(dataValBuf, 0, dataBuffer, flashAddress, dataLen); endAddr = flashAddress + dataLen; break; case 1: //文件结束 if (endAddr == 0) { return false; } else { return true; } //break; case 2: case 3: case 5: //扩展段地址, 开始段地址, 开始线性地址’ continue; case 4: //扩展线性地址 if (dataLen == 2) { LineAddOffestBase = (dataValBuf[0] * 256 + dataValBuf[1]) * 65536; } else { return false; //确认DataLen必须是2,否则报错 } break; default: return false; } } } return false; } public static void StrToHex(byte[] pbDest, byte[] pbSrc, UInt16 nLen) { byte h1 = 0; byte h2 = 0; byte s1 = 0; byte s2 = 0; int i = 0; for (i = 0; i < nLen; i++) { h1 = pbSrc[2 * i]; h2 = pbSrc[2 * i + 1]; s1 = (byte)(toupper(h1) - 0x30); if (s1 > 9) { s1 -= 7; } s2 = (byte)(toupper(h2) - 0x30); if (s2 > 9) { s2 -= 7; } pbDest[i] = (byte)(s1 * 16 + s2); } } private void StrToHex(ref UInt16 pbDest, byte[] pbSrc) { byte[] pBufDest = new byte[2]; byte h1 = 0; byte h2 = 0; byte s1 = 0; byte s2 = 0; UInt16 i = 0; for (i = 0; i < 2; i++) { h1 = pbSrc[2 * i]; h2 = pbSrc[2 * i + 1]; s1 = (byte)(toupper(h1) - 0x30); if (s1 > 9) { s1 -= 7; } s2 = (byte)(toupper(h2) - 0x30); if (s2 > 9) { s2 -= 7; } pBufDest[i] = (byte)(s1 * 16 + s2); } //pbDest = (pBufDest(0) << 8) + pBufDest(1) pbDest = (UInt16)(pBufDest[0] * 256 + pBufDest[1]); } private byte StrToHex(/*object*/ int src) { if (Convert.ToInt32(src) >= 0x30 && Convert.ToInt32(src) <= 0x39) { return Convert.ToByte((src - 0x30)); } else if (Convert.ToInt32(src) >= 0x41 && Convert.ToInt32(src) <= 0x46) { return Convert.ToByte((src - 0x41 + 10)); } else if (Convert.ToInt32(src) >= 0x61 && Convert.ToInt32(src) <= 0x66) { return Convert.ToByte((src - 0x61 + 10)); } else { return 0; } } public static byte toupper(byte val) { if (val >= 0x61 && val <= 0x7A) { return (byte)(val - 0x20); } else { return val; } } /// /// 和校验 /// 求Byte数组的和校验 /// /// Byte数组 /// public byte GetSumChecks(byte[] dataPacket, ref int len) { int sum = 0; for (var idx = 0; idx < len; idx++) { sum += dataPacket[idx]; sum &= 0xFF; } sum = (~sum) & 0xFF; return (byte)sum; } //&H public byte[] GetStringToDataByte(string str) { List dataList = new List(); for (int index = 0; index < str.Length; index += 2) { dataList.Add(Convert.ToByte($"{str.Substring(index, 2)}")); } return dataList.ToArray(); } /// /// 16进制原码字符串转字节数组 /// /// "AABBCC"或"AA BB CC"格式的字符串 /// public static byte[] ConvertHexStringToBytes(string hexString) { hexString = hexString.Replace(" ", ""); if (hexString.Length % 2 != 0) { throw new ArgumentException("参数长度不正确,必须是偶数位。"); } byte[] returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) { returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); } return returnBytes; } /// /// Byte[] 转 File /// /// public void ByteToFile(byte[] fileData) { string fileName = DateTime.Now.ToString("yyyyMMddhhmmss") + ".bin"; string dirPath = @"D:\测试"; if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath); string filePath = Path.Combine(dirPath, fileName); FileStream fileStream = new(filePath, FileMode.Create); fileStream.Write(fileData, 0, fileData.Length); fileStream.Close(); } public string HexStringToBytes(int set) { string str = set.ToString("X6"); return str; } /// Name: CRC-16/IBM x16+x15+x2+1 /// Poly: 0x8005 /// Init: 0x0000 /// Refin: true /// Refout: true /// Xorout: 0x0000 ///************************************************************************* public static byte[] Crc16(byte[] buffer, int start = 0, int len = 0) { if (buffer == null || buffer.Length == 0) return null; if (start < 0) return null; if (len == 0) len = buffer.Length - start; int length = start + len; if (length > buffer.Length) return null; ushort crc = 0;// Initial value for (int i = start; i < length; i++) { crc ^= buffer[i]; for (int j = 0; j < 8; j++) { if ((crc & 1) > 0) crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005 else crc = (ushort)(crc >> 1); } } byte[] ret = BitConverter.GetBytes(crc); Array.Reverse(ret); return ret; } public static int NetCRC16_Data(byte[] aStr, int len, int crc_id) { int xda, xdapoly; int i, j, xdabit; xda = 0xFFFF; xdapoly = 0xA001; // (X**16 + X**15 + X**2 + 1) for (i = 0; i < len; i++) { if ((i == crc_id) || (i == (crc_id + 1))) { xda ^= 0x00; } else { xda ^= aStr[i]; } for (j = 0; j < 8; j++) { xdabit = (byte)(xda & 0x01); xda >>= 1; if (xdabit!=0) xda ^= xdapoly; } } return xda; } } }