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;
} }

 


java 实现hex文件转换bin保存至内存中的更多相关文章

  1. .hex文件和.bin文件的区别

    博客转之于:  http://mini.eastday.com/a/160627003502858.html HEX文件和BIN文件是我们经常碰到的2种文件格式.下面简单介绍一下这2种文件格式的区别: ...

  2. hex文件和bin文件区别

    HEX文件和BIN文件是我们经常碰到的2种文件格式.因为自己也是新手,所以一直对这两个文件懵懵懂懂,不甚了解,最近在做STM32单片机的IAP更新,其中要考虑HEX文件和BIN文件,所以需要学习下这两 ...

  3. javafx这些学会后,开发就不难了,往tablecloumn列中添加按钮,修改javafx中tableview中tablecell中的值,修改完回车表示保存到内存中

    javafx开发过程中遇见难题,往tablecloumn列中添加按钮 想了很久的方法,也配有办法判断每行中有数据的地方添加按钮set bank_caozuo.setCellFactory((col)- ...

  4. Java常量,变量,对象(字面量)在JVM内存中的存储位置

    Java常量,变量,对象(字面量)在JVM内存中的存储位置 2019-02-26 18:13:09 HD243608836 阅读数 540  收藏 更多 分类专栏: JAVA jvm   苦苦研究了快 ...

  5. PHP hex文件及bin文件读取

    背景:做物联网时经常会有软件上传这种操作,上传的软件包文件常见的是hex和bin这两种. 一 hex文件读取 1 首先我们需要了解hex文件内容格式 (图及下面说明来自网络,侵权必删) :(冒号)每个 ...

  6. java实现xml文件读取并保存到对象

    首先浅聊一下解析xml的四种方式: 1.DOM方式:有缺点但是这个缺点却也是他的优点.下面详细介绍: 以树形的层次结构组织节点或信息片断集合,可以获得同一个文档中的多处不同数据.使用起来简单. 优点是 ...

  7. java动态编译类文件并加载到内存中

    如果你想在动态编译并加载了class后,能够用hibernate的数据访问接口以面向对象的方式来操作该class类,请参考这篇博文-http://www.cnblogs.com/anai/p/4270 ...

  8. java前端传入的json字符串保存到表中的方法

    表 service_goods_base 字段如下: 传入的json 字符串: servicePictureArray  :  [{"picServiceUrl": "h ...

  9. java成员变量和局部变量的初始化和内存中的运行机制

    成员变量: 当系统加载类或创建类的实例时,系统会自动为成员变量分配内存空间,并在分配内存空间后,自动为成员变量指定初始值. eyeNum是类属性.name是实例属性 所有person实例访问eyeNu ...

随机推荐

  1. 一键安装metasploit(linux,os x)

    curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit- ...

  2. JAVA RPC (五) 之thrift序列化RPC消息体

    让大家久等了.继续更新thrift序列化的消息体,下面我们一步一步的看一看thrift的rpc是怎么实例化消息体的. 首先我们先准备一个request文件 namespace java bky str ...

  3. 数据库主库从库宕机重启后binlog数据同步

    由于阿里云经典网络迁移到专用网络,一不小心没有先预备方案调整网段, 导致实例无法以内网IP形式访问数据库,被迫进行数据库停机后网络网段调整,导致宕机了几个小时...被客户各种投诉爆了.. 基于这次数据 ...

  4. OpenDialog文件多选

    procedure TForm1.OpenFileListClick(Sender: TObject); var openDialog: TOpenDialog; I: Integer; begin ...

  5. 学号 20175201张驰 《Java程序设计》第5周学习总结

    学号 20175201张驰 <Java程序设计>第5周学习总结 教材学习内容总结 第六章 ·1.接口的接口体中只可以有常量和abstract方法. ·2.和类一样,接口也是Java中一种重 ...

  6. mac OSx 安装 mysqlclient

    首先需要安装  按照提示操作 brew install mysql-connector-c 然后 修改mysql_config 执行mysql_config可以看到文件所在位置 我的目录放在 /usr ...

  7. [linux系统]XFS (vda3):Corruption detected.Unmount and run xfs_repair 简单解决办法

    今天kvm的centos系统,rm -rf时报错,具体如下: rm: cannot remove ‘log-0/case1/log_net’: Input/output errorrm: cannot ...

  8. RCNN的流程

    步骤一: 找到一个CNN分类模型 步骤二: 对于这个模型修改最后的分类层,为21类,去掉最后一个全连接层 步骤三: 根据选择性搜索提取图像的候选区域(框) 对于候选框修改大小以适应CNN输入,然后得出 ...

  9. Kafka笔记4(消费者)

    消费者和消费群组: Kafka消费者从属于消费者群组,一个群组里的消费者订阅的是同一个主题,每个消费者接收主题的一部分分区消息 消费者的数量不要超过主题分区的数量,多余的消费者只会被闲置 一个主题可以 ...

  10. PHP----------线程安全和非线程安全的介绍

    1.Linux下的PHP,没有线程安全版和非线程安全版之分.从2000年10月20日发布的第一个Windows版的PHP3.0.17开始的都是线程安全的版本,直至5.2.1版本开始有Thread Sa ...