设为首页 收藏本站
查看: 1248|回复: 0

[经验分享] Python二进制文件与十六进制文本文件转换

[复制链接]

尚未签到

发表于 2017-5-8 08:35:11 | 显示全部楼层 |阅读模式
  Python有一个binhex模块,在http://docs.python.org/library/binhex.html,用来Encode and decode binhex4 files。我没搞懂binhex4格式,搜索了很久,找到一个讲的相对比较好的http://www.5dmail.net/html/2006-3-2/200632222823.htm
  控制欲强的人,对未知或不可控充满恐惧。自己写个二进制与十六进制文件转换也许有点重复发明轮子的嫌疑,但是实现起来并没有想象的那么复杂,同时增加可控可用度,还有些意想不到的收获。

  ·filehelper
  在《python判断对象是否为文件对象(file object)》中介绍了判断对象是否为文件对象(file object)的方法。这里就派上用场了。
  还要介绍一个同时处理文件输入输出的帮助函数:

[python] view plaincopyprint?





  • def fileinoutpattern(inp, out, callback=None, inmode="r", outmode="wb"):

  • """
  • Make sure that 'inp' and 'out' has been 'converted' to file objects,
  • and call 'callback' with them, finally clear it up.
  • """
  • # Set up
  • fin = inp

  • if not isfilelike_r(fin):
  • fin = open(inp, inmode)
  • fout = out

  • if not isfilelike_w(fout):
  • fout = open(out, outmode)
  • # Call the 'callback'

  • result = None

  • if callback != None:
  • result = callback(fin, fout)
  • # Clear up

  • if not isfilelike_r(inp):
  • fin.close()

  • if not isfilelike_w(out):
  • fout.close()

  • return result



def fileinoutpattern(inp, out, callback=None, inmode="r", outmode="wb"):
"""
Make sure that 'inp' and 'out' has been 'converted' to file objects,
and call 'callback' with them, finally clear it up.
"""
# Set up
fin = inp
if not isfilelike_r(fin):
fin = open(inp, inmode)
fout = out
if not isfilelike_w(fout):
fout = open(out, outmode)
# Call the 'callback'
result = None
if callback != None:
result = callback(fin, fout)
# Clear up
if not isfilelike_r(inp):
fin.close()
if not isfilelike_w(out):
fout.close()
return result


  1、判断inp是否为可读文件对象,如果不是就调用open,以inmode模式打开inp所指文件,并赋值给fin
  2、判断out是否为可写文件对象,如果不是就调用open,以outmode模式打开out所指文件,并赋值给fou
  3、如果callback不为None就调用它,并将返回结果保存在result
  4、如果fin是我们自己打开的就关闭它;如果传进来的就是文件对象,则不关闭,避免重复关闭和非用户想要的关闭;
  5、如果fout是我们自己打开的就关闭它;如果传进来的就是文件对象,则不关闭,避免重复关闭和非用户想要的关闭;
  6、将callback的结果返回
  这个很重要,却很简单。当然也可以写成类,像JunitTestCase那样的,写seuptearDown方法,分别在调用callback前后执行,这里这个函数就够了。
  ·binhex
  回到我们的主题,有了这个帮助函数,怎么把二进制文件转成十六进制形式呢?

[python] view plaincopyprint?





  • def binhex(inp, out, extfun=lambda x: x, blocksize=256):

  • """
  • Convert a binary file 'inp' to binhex file output.
  • The inp may be a filename or a file-like object supporting read() and close() methods.
  • The output parameter can either be a filename or a file-like object supporting a write() and close() method.
  • """

  • def _binhex(fin, fout):

  • filesize = 0

  • while True:
  • chunk = fin.read(blocksize)

  • if chunk:
  • redlen = len(chunk)

  • for b in chunk:

  • fout.write('%02X ' % extfun(ord(b)))

  • fout.write('\n')
  • filesize += redlen

  • else:

  • break

  • return filesize

  • return fileinoutpattern(inp, out, _binhex, inmode="rb", outmode="w")



def binhex(inp, out, extfun=lambda x: x, blocksize=256):
"""
Convert a binary file 'inp' to binhex file output.
The inp may be a filename or a file-like object supporting read() and close() methods.
The output parameter can either be a filename or a file-like object supporting a write() and close() method.
"""
def _binhex(fin, fout):
filesize = 0
while True:
chunk = fin.read(blocksize)
if chunk:
redlen = len(chunk)
for b in chunk:
fout.write('%02X ' % extfun(ord(b)))
fout.write('\n')
filesize += redlen
else:
break
return filesize
return fileinoutpattern(inp, out, _binhex, inmode="rb", outmode="w")


  1、需要inpout两个参数,指明输入和输出文件,一个应用在每个字节上的函数extfun,默认块大小为256字节;
  2、定义一个嵌套的函数_binhex,实现处理逻辑:每次读入blocksize大小的数据,逐字节调用extfun处理,将处理的结果转成十六进制形式,并写入fout;每blocksize数据后添加换行;返回处理字节数;
  3、调用fileinoutpattern传递对应的参数;
  这里我们就可以发现,有了这个帮助函数,我们的函数变得非常简洁,逻辑也十分清晰。
  ·hexbin
  binhex类似,将十六进制格式文本文件转成二进制文件也很简单:

[python] view plaincopyprint?





  • def hexbin(inp, out, extfun=slambda x: x):

  • """
  • Decode a binhex file inp to binary file outpu.
  • The inp may be a filename or a file-like object supporting read() and close() methods.
  • The output parameter can either be a filename or a file-like object supporting a write() and close() method.
  • """

  • def _hexbin(fin, fout):

  • for line in fin:

  • for i in range(len(line)/3):

  • x = int(line[3*i:3*(i+1)], 16)

  • fout.write(struct.pack('B', extfun(x)))

  • fileinoutpattern(inp, out, _hexbin, inmode="r", outmode="wb")



def hexbin(inp, out, extfun=slambda x: x):
"""
Decode a binhex file inp to  binary file outpu.
The inp may be a filename or a file-like object supporting read() and close() methods.
The output parameter can either be a filename or a file-like object supporting a write() and close() method.
"""
def _hexbin(fin, fout):
for line in fin:
for i in range(len(line)/3):
x = int(line[3*i:3*(i+1)], 16)
fout.write(struct.pack('B', extfun(x)))
fileinoutpattern(inp, out, _hexbin, inmode="r", outmode="wb")

  1、传人inpout作为输入和输出文件,一个应用在转换后每个字节上的函数extfun
  2、定义一个嵌套函数_hexbin,实现处理逻辑:逐行读入,每3个字符一组,去掉空格,转成整数,在该整数上调用extfun,写入fout
  3、调用fileinoutpattern传递对应的参数;
  ·测试代码

[python] view plaincopyprint?





  • def test():

  • """
  • Test case.
  • """
  • # binhex test

  • zipfilename = r"D:\2.zip"

  • binhex(zipfilename, r"D:\2.1.txt")

  • with open(zipfilename, "rb") as fin:

  • binhex(fin, r"D:\2.2.txt")

  • with open(r"D:\2.3.txt", "w") as fout:
  • binhex(zipfilename, fout)

  • with open(zipfilename, "rb") as fin, open(r"D:\2.4.txt", "w") as fout:
  • binhex(fin, fout)
  • # hexbin test

  • txtfile = r"D:\2.1.txt"

  • hexbin(txtfile, r"D:\2.1.zip")

  • with open(txtfile, "r") as fin:

  • hexbin(fin, r"D:\2.2.zip")

  • with open(r"D:\2.3.zip", "wb") as fout:
  • hexbin(txtfile, fout)

  • with open(txtfile, "r") as fin, open(r"D:\2.4.zip", "wb") as fout:
  • hexbin(fin, fout)

  • def XOR(x):

  • def _XOR(y):

  • return x ^ y

  • return _XOR

  • xor0x13 = XOR(0x13)

  • binhex(zipfilename, r"D:\2.encode.txt", extfun=xor0x13)

  • hexbin(r"D:\2.encode.txt", r"D:\2.5.zip", extfun=xor0x13)

  • print "OK."



def test():
"""
Test case.
"""
# binhex test
zipfilename = r"D:\2.zip"
binhex(zipfilename, r"D:\2.1.txt")
with open(zipfilename, "rb") as fin:
binhex(fin, r"D:\2.2.txt")
with open(r"D:\2.3.txt", "w") as fout:
binhex(zipfilename, fout)
with open(zipfilename, "rb") as fin, open(r"D:\2.4.txt", "w") as fout:
binhex(fin, fout)
# hexbin test
txtfile = r"D:\2.1.txt"
hexbin(txtfile, r"D:\2.1.zip")
with open(txtfile, "r") as fin:
hexbin(fin, r"D:\2.2.zip")
with open(r"D:\2.3.zip", "wb") as fout:
hexbin(txtfile, fout)
with open(txtfile, "r") as fin, open(r"D:\2.4.zip", "wb") as fout:
hexbin(fin, fout)
def XOR(x):
def _XOR(y):
return x ^ y
return _XOR
xor0x13 = XOR(0x13)
binhex(zipfilename, r"D:\2.encode.txt", extfun=xor0x13)
hexbin(r"D:\2.encode.txt", r"D:\2.5.zip", extfun=xor0x13)
print "OK."

  1、这段测试代码用来测试功能是否正确实现已经足够了;
  2、我们定义了XOR(x)的工厂方法,来生产异或函数对象,代码中我们生产了与0x13疑惑的函数对象xor0x13=XOR(0x13)
  3、通过两次异或可以还原数据本身
  ·小结
  AOP:面向切面编程,也许这个例子没有表现的那么明显。我们将“二进制/十六进制转换”与“文件()处理、文件关闭”等操作分开,作为该问题的两个不同切面。这样的好处就是,我们可以分开修改其中任意一个切面,而不影响或很少影响到另一个,换句话说给我们更大的灵活性和适应性,还有代码重用性。
  嵌套函数:作为Python的一大特色,我们见到了它的用场。
  工厂方法Factory Method:我们使用了XOR这个工厂方法来生产异或函数对象

源代码下载binhex.zip

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-374418-1-1.html 上篇帖子: python中使用optparse模块简化命令行编写的复杂度 下篇帖子: Learn Python The Hard Way学习(21)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表