python长度转换代码_任意长度HEX⽂件的解析(Python实
现)
1. 程序的功能
可解析⼤于64KB的HEX⽂件。限于时间条件,笔者只测试了两个样例,数据域⼤⼩分别为8332B和1.61MB
将解析得到的结果打印出来,包括:
- 起始地址
- 末尾地址
- 数据域尺⼨(单位:字节)
保存数据域的内容为bin⽂件以便查验和后续处理
2. 程序解读
HEX⽂件解析,相关函数:hex2bin()
考虑到HEX⽂件通常不会很⼤,所以⼀次性读取全部内容,每1⾏为1个list,然后逐⾏分析
通过识别每1⾏的TT字段来执⾏相应的操作,流程图如下:
(1)数据打包
相关函数:char2hex()
通过readlines函数读取到的是⼀⾏⾏字符串,如第⼀⾏是“:020*********F2”,此外末尾还包含⼀个不可见的回车符号。
我们要将数字字符转换成对应的整型数据以便运算和存储,⾏⾸的冒号和⾏尾的回车符仅⽤于格式判断,对于数据提取是⽆⽤的,故去除。
HEX格式定义中的记录域是以字节为最⼩单位的,所以还需要将两个整型字符拼成1个字节。
python提供的⾼阶函数map()和切⽚操作,极⼤地⽅便了我们对HEX⽂本进⾏信息提取和格式转换。
char2hex()函数最终返回的是如下形式的整型列表:[0x02,0x00,0x00,0x04,0x08,0x00,0xF2]
(2)校验和
相关函数:checksum()
得到了1⾏数据的整型列表以后,最好对该⾏数据校验⼀下。
按照规定,每⾏记录的倒数第1个字节是校验和(Checksum),校验算法为:
0x100-((除了冒号以外的所有数据以字节为单位相加)%256)
笔者的代码实现如下:sum = (0x100 - (reduce(lambda x,y:x+y,line[:-1]) % 256)) % 256
之所以最后要再对256取模,是考虑到算出来的结果正好为0x100的情况,在C语⾔⾥,不做这⼀步当然OK,因为C语⾔中数据类型有⾃⾝的固定长度,
超出长度的⾼位部分会⾃动截断,对于8位⽆符号数,0x100==0x00是成⽴的,⽽Python中的int是动态变化的,数据在内存中的组织不像C那样读编程者那么直观,不存在数据类型的定义,0x100和0x00当然就是不相等的。
(3)保存bin⽂件
相关函数:wr_bin()
执⾏完hex2bin()后,HEX⽂件中数据域全都按顺序,从低字节到⾼字节被写⼊到了1个整型list中,
但按照python的要求,将每个元素转换为byte类型才能写⼊到⼆进制⽂件中。代码如下:
bin_buf_byte = list(map(six.int2byte,bin_buf))
(4)运⾏结果分析
笔者所测试的两个样例hex都是由STM32的⼯程编译⽽来。
查看打印输出的运⾏结果:addr_start代表起始地址,内容⽐较。
hex和bin⽂件在对应位置上分别截取1⾏,还可以⽤⿏标在输出的bin⽂件上右击,查看“属性”-“常规”-“⼤⼩”来验证内容是否遗漏。从以上两个列表可以直观地看出,程序正确地解析了hex⽂件的内容。
3. 代码实现# -*- coding: utf-8 -*-
# File Name : hex2bin.py
# Version : V1.0.0001
# Date : 2019/03/06
# Author : qipeng_jiang
import os
import time
import six
from functools import reduce
# get '.hex' file name from current path
def getFileNamebyEX(path):
f_list = os.listdir(path)
for i in f_list:
filename = os.path.splitext(i)[0]
extname = os.path.splitext(i)[1]
if extname == '.hex':
print(" *Hex file : " + filename + extname+'*')
return i
bin_buf = []# raw data of binary is to be stored here
def hex2bin(hex_file_name,bin_file_name):
with open(hex_file_name,'r') as frd:
print(' *Hex file : \''+hex_file_name+'\''+' is opened*')
byte_num = 0
for line adlines():
#line.strip(); #cut off CR
if(line[0] == ':'):
if(line[7:9] == '04'): #Extended Linear Address Record
#print('Extended Linear Address Record');
line = char2hex(line)
if checksum(line) == 0: #checksum passed
addr_h = (line[4]<<24) +(line[5]<<16)
else:
print('checksum failed!'+str(list(map(hex,line))))
elif (line[7:9] == '00'): #Data Record
line = char2hex(line)
if checksum(line) == 0:
addr_l = (line[1]<<8) + line[2]
LL = line[0]
byte_num = byte_num + LL
for data in line[4:-1]:
bin_buf.append(data)
if LL!=0x10:
addr_end = addr_h + addr_l + LL - 1
else:
pass
else:
print('checksum failed!'+str(list(map(hex,line))))
elif(line[7:9] == '05'):
#print('Extended Segment Address Record');
line = char2hex(line)
if checksum(line) == 0: pass
else:
print('checksum failed!'+str(list(map(hex,line))))
elif(line[7:9] == '01'): #End of FileRecord
#print('End of FileRecord');
line = char2hex(line)
if checksum(line) == 0:
print(' *Hex file successed resolved*')
print(' *addr_start: 0x%08X' %(addr_end + 1 - len(bin_buf))) print(' *addr_end : 0x%08X' %addr_end)
print(' *Total size : %d Bytes'%len(bin_buf))
else:
print('checksum failed!'+str(list(map(hex,line))))
else:
pass #don't care
else:
print('illegal format!')
# write data in bin_buf to '*.bin' file
def wr_bin(bin_buf):
bin_buf_byte = list(map(six.int2byte,bin_buf))
with open(bin_file_name,'wb') as fwrb:
print(' *Bin file \''+bin_file_name+'\''+' is opened for write*')
for data in bin_buf_byte:
fwrb.write(data)
print(' *Bin file is successfully written!*')
#one line string to hex-8 list,except ':' and CR
def char2hex(line):
line=list(map(ord,list(line)))
for num in range(len(line)):
if line[num]>=0x30 and line[num]<=0x39:
line[num] = line[num] - 0x30
elif line[num]>=0x41 and line[num]<=0x5A:
line[num] = line[num] - 55
else:
pass
line=line[1:-1] #delete CR and ':', in terms of byte
for i in range(0,len(line),2):
line[i] = line[i]*16 + line[i+1]
newline = line[::2]
return newline
#checksum calculation of every line
def checksum(line):
#considering if the checksum calculation result is 0x100
sum = (0x100 - (reduce(lambda x,y:x+y,line[:-1]) % 256)) % 256
if sum == line[-1]: #check if sum calculated is equal to checksum byte in hex file
return 0
else:
return 1
starttime = time.clock()
hex_file_name = getFileNamebyEX('.')
bin_file_name = hex_file_name[:-4]+'.bin'
python代码转换hex2bin(hex_file_name,bin_file_name)
wr_bin(bin_buf)
endtime = time.clock()
print(' Time elapsed:' + str(endtime-starttime))
4. 脚本运⾏
拷贝 .hex ⽂件到 python 脚本同级⽬录下,直接运⾏。打印log内容如下:
注意:本站所有⽂章除特别说明外,均为原创,转载请务必以超链接⽅式并注明作者出处。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论