hex 文件的格式,以文件中某一行字符串(16進制)為例:
:10 0830 00 020C5D0224B3FFFFFFFFFFFFFFFFFFFF 7E
10,長度,轉換成10進制,也就是16B 大小,這里是32個字符,因為16進制中,2個字符占一個字節,可以不管。
0830,地址,轉換成10進制好計算,數據存入字節數組時,可以當做數組下標來使用,方便計算兩個地址間的差值。
00,這里表示數據記錄,還有其他類型百度便知,可以不管。
02...FF,數據部分。主要就是把這一部分轉成bin文件。
7E,校驗使用。
新建一個java工程加入以下代碼如有問題請留言
import com.mpos.init.model.FileStruct; import com.mpos.init.model.HexRec; import java.io.*; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { System.out.println(readFile() + ""); } /** * @return -1 文件解析錯誤 0 表示成功 -2 初始buf太小 */ private static int readFile() { File mfile = new File("D:\\MP100-01-V1.2-20180115.hex"); List<HexRec> hexRecs = new ArrayList<>(); InputStream inputStream = null; BufferedReader bufferedReader = null; FileOutputStream fileOutputStream = null; int i = 0, j = 0; //索引 int l_addr; int len = 0;//數組索引 long minAddr = 4294967295L; FileStruct hex = new FileStruct(); try { if (mfile == null) { System.out.println("文件為空"); } inputStream = new FileInputStream(mfile); //轉成 reader 以 行 為單位讀取文件 bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); //當前行字符串 String hexLineStr; //當前行數 int hexLineNum = 0; while ((hexLineStr = bufferedReader.readLine()) != null) { System.out.println(hexLineStr); hexLineNum++; if (!hexLineStr.startsWith(":", 0)) { return -1; } if (hexLineStr.length() >= 11) { hex.setStart(":"); byte[] data = hexString2ByteArray(hexLineStr.substring(1));//判斷數據的正確是是不是0—F if (data == null) return -1; //解析數據 hex.setLength(Integer.parseInt(hexLineStr.substring(1, 3), 16)); hex.setOffset(Integer.parseInt(hexLineStr.substring(3, 7), 16)); hex.setType(Integer.parseInt(hexLineStr.substring(7, 9), 16)); /////////////////////////////////////////////////////////////////// //判斷數據類型是否合法, 未處理05的數據 if (0x00 != hex.getType() && 0x01 != hex.getType() && 0x02 != hex.getType() && 0x04 != hex.getType() && 0x05 != hex.getType()) { return -1; } if (0x05 == hex.getType()) {//不處理05類型的數據 continue; } if (hex.getLength() > 0) { hex.setData(hexLineStr.substring(9, 9 + hex.getLength() * 2)); } if (!checkValue(hexLineStr)) return -1; switch (hex.type) { case 0x00: //本行的數據類型為“數據記錄” //本行所從屬的數據類型為“數據記錄” if (0x00 == hex.format) { l_addr = hex.offset; } //本行所從屬的數據類型為“擴展段地址記錄”(HEX86)--20位地址 else if (0x02 == hex.format) { l_addr = (hex.address << 4) + hex.offset; } //本行所從屬的數據類型為“擴展線性地址記錄”(HEX386)--32位地址 else if (0x04 == hex.format) { l_addr = (hex.address << 16) + hex.offset; } //文件結束 else { i = 1; break; } //記錄地址中的最大值 System.out.println("l_addr:" + l_addr); if (minAddr > l_addr) minAddr = l_addr; if (hex.length > 0) { HexRec hexRec = new HexRec(); hexRec.setAddr(l_addr); hexRec.setLen(hex.length); hexRec.setBuf(hex.data); hexRecs.add(hexRec); len += hex.length; } break; case 0x01: //本行的數據類型為“文件結束記錄” //文件結束記錄的數據個數一定是0x00 if (hex.length == 0x00) i = 1; hex.format = 0x01; break; case 0x02: //本行的數據類型為“擴展段地址記錄” //擴展段地址記錄的數據個數一定是0x02 if (hex.length != 0x02) i = 3; //擴展段地址記錄的地址一定是0x0000 if (hex.offset != 0x0000) i = 3; //更改hex從屬的數據類型 hex.format = 0x02; //獲取段地址 String hexStr = hex.getData().substring(0, 4); byte[] hexBytes = hexString2ByteArray(hexStr); hex.address = (hexBytes[0] << 8 | hexBytes[1]); break; case 0x04://本行的數據類型為“擴展線性地址記錄” //擴展線性地址記錄中的數據個數一定是0x02 if (hex.length != 0x02) i = 4; //擴展線性地址記錄的地址一定是0x0000 if (hex.offset != 0x0000) i = 4; //更改hex從屬的數據類型 hex.format = 0x04; //獲取高16位地址 hexStr = hex.getData().substring(0, 4); hexBytes = hexString2ByteArray(hexStr); hex.address = (hexBytes[0] << 8 | hexBytes[1]); break; } } //如果出現異常或文件結束退出循環 if (i == 1) { break; } if (i > 0) { return -1;//文件解析出錯 } } len = 0; int minLen = 0; int offset = 0; StringBuffer buffer = new StringBuffer(); for (int a = 0; a < hexRecs.size(); a++) { offset = (int) (hexRecs.get(a).getAddr() - minAddr); buffer.append(hexRecs.get(a).getBuf()); if (minLen < offset + hexRecs.get(a).getLen()) { minLen = offset + hexRecs.get(a).getLen(); } len += hexRecs.get(a).getLen(); } if (len < minLen) { len = minLen; } System.out.println(buffer); } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } if (bufferedReader != null) { bufferedReader.close(); } if (fileOutputStream != null) { fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } return 0; } /** * 將16進制字符串轉換為byte[] * * @param hexString * @return */ public static byte[] hexString2ByteArray(String hexString) { try { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } catch (Exception e) { return null; } } /** * Convert char to byte * * @param c char * @return byte */ public static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); } /** * 校驗和必然是256的整數倍,如果有余數則認為校驗和失敗 * * @return false 校驗失敗 反正成功 */ public static boolean checkValue(String hexLineStr) { byte[] buf = hexString2ByteArray(hexLineStr.substring(1)); byte temp = 0; for (int i = 0; i < buf.length; i++) { temp += buf[i]; } if (temp % 0xFF == 0) { return true; } return false; } }
FileStruct對象代碼
public class FileStruct { public String start = ":"; //每一條Hex記錄的起始字符“:” public int length = 0x00; //數據的字節數量 public int address = 0x0000; //數據存放的地址 public int type = 0xFF; //HEX記錄的類型 public String data;//一行最多有16個字節的數據 public int check = 0xAA; //校驗和 public int offset = 0x0000; //偏移量 public int format = 0x00; //數據行所從屬的記錄類型 public String getStart() { return start; } public void setStart(String start) { this.start = start; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } public int getAddress() { return address; } public void setAddress(int address) { this.address = address; } public int getType() { return type; } public void setType(int type) { this.type = type; } public String getData() { return data; } public void setData(String data) { this.data = data; } public int getCheck() { return check; } public void setCheck(int check) { this.check = check; } public int getOffset() { return offset; } public void setOffset(int offset) { this.offset = offset; } public int getFormat() { return format; } public void setFormat(int format) { this.format = format; } }
HexRec對象代碼
public class HexRec { private int addr; private int len; private String buf; public HexRec() { } public int getAddr() { return addr; } public void setAddr(int addr) { this.addr = addr; } public int getLen() { return len; } public void setLen(int len) { this.len = len; } public String getBuf() { return buf; } public void setBuf(String buf) { this.buf = buf; } }