java 实现hex文件转换bin保存至内存中

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

}

 


原文地址:https://www.cnblogs.com/blogzhangwei/p/8781183.html

时间: 2024-08-01 16:40:46

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

将文件转换为数组保存在内存中

#include <stdio.h> #include <stdlib.h> int main() { FILE *image = fopen("big_face.yuv", "r"); if(NULL == image) { printf("open file failed!"); return 0; } fseek(image, 0, SEEK_END); int nFileLen = ftell(image); re

HEX文件和BIN文件格式的区别

在单片机开发中HEX文件和BIN文件是非常常见的烧写文件格式,以常用开发环境Keil为例,分别创建HEX和BIN文件,比如: 1.创建HEX:在Keil里面可以通过勾选[魔法棒>Output>Creat HEX File]让工程输出HEX文件. 2.创建BIN:在Keil中在[魔法棒>User>After Build/Rebuild]标签下勾选Run #1,同时在其对应的User Command文本框中输入 fromelf --bin [email protected] !L 编译

hex文件和bin文件区别

HEX文件和BIN文件是我们经常碰到的2种文件格式.因为自己也是新手,所以一直对这两个文件懵懵懂懂,不甚了解,最近在做STM32单片机的IAP更新,其中要考虑HEX文件和BIN文件,所以需要学习下这两种文件.下面是最近的我的了解,如有不对地方还请指正. HEX文件是包括地址信息的,而BIN文件格式只包括了数据本身 在烧写或下载HEX文件的时候,一般都不需要用户指定地址,因为HEX文件内部的信息已经包括了地址.而烧写BIN文件的时候,用户是一定需要指定地址信息的. HEX文件格式 HEX文件都是由

PHP hex文件及bin文件读取

背景:做物联网时经常会有软件上传这种操作,上传的软件包文件常见的是hex和bin这两种. 一 hex文件读取 1 首先我们需要了解hex文件内容格式 (图及下面说明来自网络,侵权必删) :(冒号)每个Intel HEX 记录 都由冒 号开头 : LL 是 数 据 长 度域, 它 代表 记录当 中 数 据字 节 (dd) 的 数量 : aaaa 是地址域, 它代表 记录当 中 数据的起始地址: TT是代表HEX 记录类 型的域 , 它 可能是以下 数 据 当 中的一 个: 00 – 数 据 记录(

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

首先浅聊一下解析xml的四种方式: 1.DOM方式:有缺点但是这个缺点却也是他的优点.下面详细介绍: 以树形的层次结构组织节点或信息片断集合,可以获得同一个文档中的多处不同数据.使用起来简单. 优点是:可以获得同一个文档中的多处不同数据,使用起来简单. 缺点是:需要加载整个xml文件,这对内存和资源有一定的消耗,如果是小型的xml文件可以尝试用 DOM方式解析. 经测试当用DOM方式读取大小为10M的文件时, 将会产生内存溢出异常. 2.SAX方式:在读取数据时检查数据,不用解析整个文档,因此不

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

如果你想在动态编译并加载了class后,能够用hibernate的数据访问接口以面向对象的方式来操作该class类,请参考笔者的这篇博文-(该博文暂未发布) 所谓动态编译,就是在程序运行时产生java类,并编译成class文件. 一.这里介绍两种动态编译java文件的方式. 第一种:使用Runtime执行javac命令 /** * 编译java类 * 使用Runtime执行javac命令 * @param name 类的全限定包名 不带后缀 例如com.test.Notice 而不要写成com.

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

成员变量: 当系统加载类或创建类的实例时,系统会自动为成员变量分配内存空间,并在分配内存空间后,自动为成员变量指定初始值. eyeNum是类属性.name是实例属性 所有person实例访问eyeNum都将访问person类的eyeNum属性.访问的是同一块内存.如果通过实例修改类属性,所有实例访问时都会改变. 局部变量: 局部变量定义后,必须经过显示初始化才能使用.这意味着定义了局部变量后,系统并未为这个变量分配内存空间,直到等到程序为这个变量赋值初始值时,系统才会给局部变量分配内存,并将初始

【转】java将excel文件转换成txt格式文件

在实际应用中,我们难免会遇到解析excel文件入库事情,有时候为了方便,需要将excel文件转成txt格式文件.下面代码里面提供对xls.xlsx两种格式的excel文件解析,并写入到一个新的txt文件中,数据以分隔符逗号","隔开. excel文件如图所示: 转换后的txt文件: 需要依赖4个jar包: package com.xuan.excel; import java.io.BufferedWriter; import java.io.File; import java.io.

bin文件转换为hex文件C语言实现

对于嵌入式而言,hex文件可能大家再熟悉不过了,对,我们大学时学习的51单片机编写的代码在keil上编译后就生成了hex文件.那bin文件又是什么意思呢,它又和hex文件的区别在哪?这也不是本文的重点,下面简单的描述下: 最通俗的来讲,hex是带地址的,用下载器下载时,不需要设置偏移地址,它是文件流格式的,都是标准的ASCII码.而bin文件是不带地址的,全部是二进制数据流,打住一下,其实就是我们所谓的机器代码.有兴趣的同学,可以尝试着用反汇编,得到的就是汇编代码了.我所用的开发板S3C2440