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;
- }
- }
来源: http://www.bubuko.com/infodetail-2557441.html