解决python3整数数组转bytes的效率问题
昨天在做⼀道CTF题的时候碰到了⼀个图⽚异或的问题,操作⼤概如下:
将⼀个图⽚读⼊,然后每字节进⾏异或操作,核⼼代码可简化为以下:
#coding:utf-8
'''
@DateTime: 2017-11-25 13:51:33
@Version: 1.0
@Author: Unname_Bao
'''
import six
key = b' dcd~ b6^g 11 e1U7R 18!+9d dcd~ b6^g 11 e1U7R 18!+9d'
with open('pted','rb') as f:
c = f.read()
flag = b''
for i in range(32):
flag += six.int2byte(key[i%32]^c[i])
with open('flag.png','wb') as f:
f.write(flag)
然后就碰到了⼀个效率问题,跑了⼗⼏分钟都没有跑出结果,起初以为是类型转换的问题,因为⽐较急,于是换了成了C++的代码去解决,后来⼀直没多想。
今天闲下来的时候才发现代码之前的代码中存在⼀个⾮常⼤的问题:
内存申请问题
由于pted⽂件⼤⼩为6.47MB之⼤,由于我的脚本思路是不断在byte数组后添加,但忽略了其本质。
就是在内存申请过程中,由于数组长度最终为600+W⼤⼩,期间存在多次数组内存不够,需要重新申请内存的问题,⽽python中的内存申请显然没有C++的vector的push_back有效率。
⽽且python中,⽆论是list、string还是byte,也没有reserve这种函数,不能预留内存空间(这时候真的要吐槽⼀下python设计者对速度优化的考量了)。
于是只能⽤另⼀种⽅法进⾏优化,就是先⽤list申请⼀个需求⼤⼩的内存空间,然后再转为bytes使⽤,
代码如下:
#coding:utf-8
'''
@DateTime: 2017-11-26 14:09:29python获取数组长度
@Version: 2.0
@Author: Unname_Bao
'''
key = b' dcd~ b6^g 11 e1U7R 18!+9d dcd~ b6^g 11 e1U7R 18!+9d'
with open('pted','rb') as f:
c = f.read()
flag = list('1'*len(c))
for i in range(len(c)):
flag[i] = key[i%32]^c[i]
flag = bytes(flag)
with open('flag.png','wb') as f:
f.write(flag)
这样写的话⼏乎是瞬间完成任务了,但还是⽐C++慢很多,这是不可避免的。
补充:python2与python3的bytes问题
>>> s = '编程'
>>> print s
编程
>>> s
' e7 bc 96 e7 a8 8b'
>>>
在python2中直接调⽤字符串的变量的话,会打印其bytes(可以理解成⽤16进制表⽰字符串的内存地址,本质还是⼆进制)。在python2中,bytes和str是⼀回事。
为什么要有个bytes呢?因为所有数据本质都是⽤⼆进制进⾏储存的,当传输数据的时候,要把这些数据先转换成⼆进制( bytes)在进⾏传输。除此之外,python2⾥还有个单独的数据类型,把字符串解码后,
就会变成unicode。
>>> s
' e8 b7 af e9 a3 9e' #utf-8
>>> s.decode('utf-8')
u'\u8def\u98de' #unicode 在unicode编码表⾥对应的位置
>>> print(s.decode('utf-8'))
路飞 #unicode 格式的字符
原因是python2的默认编码是ASCII,后来为了⽀持多国语⾔,就想弄个unicode。但是直接把ASCII转成unicode是很费劲的,所以龟叔直接搞了⼀个新的字符类型,就叫unicode,说⽩了就是你得在内存⾥先把字符串存成unicode类型
2008年python3出世,来了个⼤变⾰:
1、把字符串的编码变成了unicode,⽂件默认编码变成了utf-8。
2、把str 和bytes 做了明确区分, str 就是unicode格式的字符, bytes就是单纯⼆进制还有⼀个很重要的是,在python3中,只有unicode给你展⽰字形,其他的编码⼀律⽤bytes展⽰,也就是说要你强制使⽤unicode。
最后再提⽰⼀下,Python只要出现各种编码问题,⽆⾮是哪⾥的编码设置出错了
常见编码错误的原因有:
Python解释器的默认编码
Python源⽂件⽂件编码
Terminal使⽤的编码
操作系统的语⾔设置
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。如有错误或未考虑完全的地⽅,望不吝赐教。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。