|  |  | 
 |  |  |  | 
 |  |  | import cn.hutool.core.util.HexUtil; | 
 |  |  | import com.dy.common.util.ByteUtil; | 
 |  |  | import com.dy.common.util.CRC16; | 
 |  |  |  | 
 |  |  | import java.io.*; | 
 |  |  | import java.util.ArrayList; | 
 |  |  | import java.util.List; | 
 |  |  | import java.util.stream.Stream; | 
 |  |  |  | 
 |  |  | 
 |  |  |  | 
 |  |  |     private static final int hexFileMinLine = 4 ; | 
 |  |  |     private static final int lineHeadEndIndex = 9 ; | 
 |  |  |     private static final int bytesSplitUnit = 512 ; | 
 |  |  |     private static final int lineValidCharCount = 43 ;//每行有效字符(冒号与十六进制)个数,例如“:1096C000DC96010010020020203E00000441000052”,但倒数第3行不受限制 | 
 |  |  |     private static final int bytesSplitUnit512 = 512 ; | 
 |  |  |  | 
 |  |  |     public static void main(String[] args) throws Exception{ | 
 |  |  |         boolean fromBytes = true ; | 
 |  |  |         boolean fromBytes = false ; | 
 |  |  |         HexFileParse obj = new HexFileParse() ; | 
 |  |  |         if(!fromBytes){ | 
 |  |  |             String filePath = "D:\\hexFile\\YuanMu_edit241007_01.hex"; | 
 |  |  |             String filePath = "D:\\hexFile\\YuanMu_20250116_01.hex"; | 
 |  |  |             //File file = new File(filePath) ; | 
 |  |  |             HexFileVo vo =  obj.doParse(filePath) ; | 
 |  |  |             System.out.println(vo.toString()); | 
 |  |  |         }else{ | 
 |  |  |             String filePath = "D:\\hexFile\\YuanMu_edit241007_01.hex"; | 
 |  |  |             String filePath = "D:\\hexFile\\YuanMu_20250116_01.hex"; | 
 |  |  |             File file = new File(filePath) ; | 
 |  |  |             byte[] fileContent = new byte[(int)file.length()] ; | 
 |  |  |             FileInputStream fileInputStream = new FileInputStream(file) ; | 
 |  |  | 
 |  |  |         HexFileVo vo = new HexFileVo() ; | 
 |  |  |         this.checkAndCalculate(vo, lineList); | 
 |  |  |         this.parse(vo, lineList); | 
 |  |  |         this.split(vo); | 
 |  |  |         this.splitBytesByUnit512(vo); | 
 |  |  |         this.calculateCrc(vo); | 
 |  |  |         return vo ; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |         HexFileVo vo = new HexFileVo() ; | 
 |  |  |         this.checkAndCalculate(vo, lineList); | 
 |  |  |         this.parse(vo, lineList); | 
 |  |  |         this.split(vo); | 
 |  |  |         this.splitBytesByUnit512(vo); | 
 |  |  |         this.calculateCrc(vo); | 
 |  |  |         return vo ; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |         if(vo.totalLines < hexFileMinLine){ | 
 |  |  |             throw new Exception("Hex文件内容行数" + vo.totalLines + "不正确(最小行数" + hexFileMinLine +")") ; | 
 |  |  |         } | 
 |  |  |         vo.calculateBytes = ((vo.totalLines - 4) * 32) / 1024 * 512 ; | 
 |  |  |         vo.calculateBytes = ((((vo.totalLines - 4) * 32) / 1024) | 
 |  |  |                 + ((((vo.totalLines - 4) * 32) % 1024) > 0?1 : 0)) | 
 |  |  |                 * 512 ; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  | 
 |  |  |                         if(!line.startsWith(":")){ | 
 |  |  |                             vo.errors.add("第" + counter + "行内容不是以:开头") ; | 
 |  |  |                         }else{ | 
 |  |  |                             line = line.substring(lineHeadEndIndex, line.length() - 2) ; | 
 |  |  |                             if(vo.bytes.length == 0){ | 
 |  |  |                                 vo.bytes = HexUtil.decodeHex(line) ; | 
 |  |  |                             if(counter != vo.totalLines - 3 && line.length() != lineValidCharCount){ | 
 |  |  |                                 //无效数据,舍弃本行数据 | 
 |  |  |                             }else{ | 
 |  |  |                                 byte[] bytes = HexUtil.decodeHex(line) ; | 
 |  |  |                                 vo.bytes = ByteUtil.bytesMerge(vo.bytes, bytes) ; | 
 |  |  |                                 line = line.substring(lineHeadEndIndex, line.length() - 2) ; | 
 |  |  |                                 if(vo.bytes.length == 0){ | 
 |  |  |                                     vo.bytes = HexUtil.decodeHex(line) ; | 
 |  |  |                                 }else{ | 
 |  |  |                                     byte[] bytes = HexUtil.decodeHex(line) ; | 
 |  |  |                                     vo.bytes = ByteUtil.bytesMerge(vo.bytes, bytes) ; | 
 |  |  |                                 } | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 以512为单位分割数据包 | 
 |  |  |      * @param bytes | 
 |  |  |      */ | 
 |  |  |     public List<byte[]> splitBytesByUnit512(byte[] bytes){ | 
 |  |  |         List<byte[]> listByte512 = new ArrayList<>(); | 
 |  |  |         if(bytes != null && bytes.length > 0){ | 
 |  |  |             int index = 0 ; | 
 |  |  |             while (true){ | 
 |  |  |                 if(index < bytes.length){ | 
 |  |  |                     byte[] bs = ByteUtil.bytesSplit(bytes, index, bytesSplitUnit512) ; | 
 |  |  |                     listByte512.add(bs) ; | 
 |  |  |                 }else{ | 
 |  |  |                     break ; | 
 |  |  |                 } | 
 |  |  |                 index += bytesSplitUnit512; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return listByte512 ; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 以512为单位分割数据包 | 
 |  |  |      * @param vo | 
 |  |  |      */ | 
 |  |  |     private void split(HexFileVo vo){ | 
 |  |  |     private void splitBytesByUnit512(HexFileVo vo){ | 
 |  |  |         if(vo.bytes != null && vo.bytes.length > 0){ | 
 |  |  |             vo.realBytes += vo.bytes.length ; | 
 |  |  |             int index = 0 ; | 
 |  |  |             while (true){ | 
 |  |  |                 if(index < vo.bytes.length){ | 
 |  |  |                     byte[] bytes = ByteUtil.bytesSplit(vo.bytes, index, bytesSplitUnit) ; | 
 |  |  |                     byte[] bytes = ByteUtil.bytesSplit(vo.bytes, index, bytesSplitUnit512) ; | 
 |  |  |                     vo.listByte512.add(bytes) ; | 
 |  |  |                     vo.totalBytes512 += bytes.length ; | 
 |  |  |                 }else{ | 
 |  |  |                     break ; | 
 |  |  |                 } | 
 |  |  |                 index += bytesSplitUnit ; | 
 |  |  |                 index += bytesSplitUnit512; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 计算CRC16 | 
 |  |  |      * @param vo | 
 |  |  |      */ | 
 |  |  |     private void calculateCrc(HexFileVo vo){ | 
 |  |  |         int crc = 0xffff ; | 
 |  |  |         if(vo.listByte512 != null && vo.listByte512.size() > 0){ | 
 |  |  |             CRC16 crc16 = new CRC16() ; | 
 |  |  |             for(byte[] bs : vo.listByte512){ | 
 |  |  |                 crc =  crc16.CRC16_table(bs.length, bs, crc) ; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         vo.bytesCrc16 = crc ; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } |