标签:直接 nts 问题 type map ref 相互转换 是什么 list
【前言】
最近用python读二进制文件,遇到一个问题:我的二进制文件里面掺杂着正常的文本,我想将里面的文本给剔除掉。解决这个问题就是写这篇文章的初衷。
二进制文件和文本文件有啥区别呢?百度知道 里面有位大佬说:在定义和存取方式上二进制文件与文本文件存在区别。
1、定义上的区别
文本文件:文本文件是一种计算机文件,它是一种典型的顺序文件,其文件的逻辑结构又属于流式文件。简单的说,文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等等。
二进制文件:是基于值编码的文件,你可以根据具体应用,指定某个值是什么意思(这样一个过程,可以看作是自定义编码)。用户一般不能直接读懂它们,只有通过相应的软件才能将其显示出来。二进制文件一般是可执行程序、图形、图像、声音等等。
从上面可以看出文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异,文本文件基本上是定长编码的(也有非定长的编码如UTF-8)。而二进制文件则可看成是变长编码,因为是值编码,多少个比特代表一个值,完全由你决定。
2、存储方式上的区别
3、文本文件和二进制文件的优缺点:
好像对于文本文件,不论是二进制方式读取还是文本方式读取,都可以;但是对于二进制文件,只可以二进制方式读取,用文本方式读取的话会报错的。
Python 读取文本文件不用多说,关键是二进制文件。
#读取文本文件
f=open(‘somefile.txt‘,‘r‘);
flist=f.readlines()
f.close()
读二进制文件,就来个压缩包吧,最近就是搞压缩包遇到问题,才想写这篇文章的。
filename=r‘C:\Users\OHanlon\Documents\python\temp\ABPO00MDG_R_20191010000_01D_30S_MO.crx.gz‘
fblist=fb.readlines()
l1=fblist[0] #b‘HTTP/1.1 200 OK\r\n‘
l15=fblist[14] #b"\xe3\xe0\x87\x91\xc..
#上面只是一部分
type(l1) #<class ‘bytes‘>
type(l15) #<class ‘bytes‘>
上面这个文件情况是这样的:用npp打开的时候,可以看到它前面有几行是文本,然后后面是乱码。通过上面python以二进制方式读取的话,直观上看,可以很明显地区分出来文本和二进制语句。
Python2 和Python3 读取二进制文件的区别
从上面可以看出来:python2 以二进制方式读文件读出来的是字符串,python3读二进制文件,读出来的是bytes。
我上面是用python3读取的,下面先考虑python3的情况。
sl1=str(l1) # "b‘HTTP/1.1 200 OK\\r\\n‘"
sl15=str(l15) # ‘b"\\xe3\\xe0\\x87\\x91\\xc..
将bytes 转化成 str ;这样就很容易看出来区别了:
好,上面已经解决了python3 的问题:r‘\x‘ in str(xx)
返回 true 就是二进制语句,返回false就是正常的文本语句。那么对于python2 怎么解决呢?(实际上我的问题已经得以解决,但是处于好奇,多尝试一下嘛)
先切换到 16 进制视图看下文件:
注:这个文件,前13行是文本。
发现并没有好的标志,做了初步尝试:
然后在网上搜了搜,发现有篇文章:
文章中的小函数如下(注意,是Python2):
#Check if a string is text or binary
‘‘‘If the string contains control or more than 30% of the characters in the string are 1, then it is binary data‘‘‘
import string
text = ‘‘.join(map(chr,range(32,127))) + ‘\r\n\t\b‘
_null_trans = string.maketrans(‘‘,‘‘)
def istext(s,text = text,threshold = 0.30):
if ‘\0‘ in s:
return False
if not s:
return True
t = s.translate(_null_trans,text) #delete char in text for s
return len(t)/(len(s) * 1.0) <= threshold
进行测试:
file=‘ABPO00MDG_R_20191010000_01D_30S_MO.crx.gz‘
fb=open(file,‘rb‘)
flist=fb.readlines()
l1=flist[0]
l15=flist[14]
fb.close()
import test; print test.istext(l1); print test.istext(l15)
perfect!
至此,在python2 和python3 中都已完美解决我遇到的问题!
>>> str=‘ohanlon‘
>>> bstr=str.encode(‘utf-8‘)
>>> bstr
b‘ohanlon‘
>>> str1=bstr.decode(‘utf-8‘)
>>> str1
‘ohanlon‘
>>> del str #得把str删了,不然下面那行会将str认为是变量str,这样就执行不了。
>>> str(bstr)
"b‘ohanlon‘"
>>> repr(bstr)
"b‘ohanlon‘"
【文章总结】
bstr=str.encode(‘utf-8‘)
str转bytesstr1=bstr.decode(‘utf-8‘)
bytes转strprint xx
和print(xx)
,而python3 只支持后者。python3 以二进制形式读文件出来的是bytes,而python2以二进制形式读文件读出来的是str。r‘\x‘ in str(xx)
返回 true 就是二进制语句,返回false就是正常的文本语句;在python2 中的解决方案是加个小函数,istext(xx)
返回 false 就是二进制语句,返回true就是正常的文本语句。#Check if a string is text or binary
‘‘‘If the string contains control or more than 30% of the characters in the string are 1, then it is binary data‘‘‘
import string
text = ‘‘.join(map(chr,range(32,127))) + ‘\r\n\t\b‘
_null_trans = string.maketrans(‘‘,‘‘)
def istext(s,text = text,threshold = 0.30):
if ‘\0‘ in s:
return False
if not s:
return True
t = s.translate(_null_trans,text) #delete char in text for s
return len(t)/(len(s) * 1.0) <= threshold
标签:直接 nts 问题 type map ref 相互转换 是什么 list
原文地址:https://www.cnblogs.com/Gou-Hailong/p/14135793.html