尝试将ascii文件转换成utf-8的编码格式.Python3有两种表示字符序列的类型:bytes和str。个人理解是,bytes是计算机能够识别的数据类型,然后str是Unicode字符,即是人比较容易理解的字符类型。
以下代码包含在debug.py文件中:
def main():
pass
if __name__ == '__main__':
main()
以bytes读取该文件,并通过 chardet.detect() 方法查看它的编码方式,并输出bytes格式(二进制数据)的字符串:
# debug.py的编码格式应该是Ascii的,然后转换成utf-8的格式
import chardet
import os
path = 'debug.py'
with open(path,'rb') as f:
data_bytes = f.read() #读取文件的二进制数据(bytes)
print(chardet.detect(data_bytes)['encoding'])#输出debug.py的编码方式
print(data_bytes)
print(type(data_bytes))
代码运行的结果如下:
ascii
b"def main():\r\n pass\r\n \r\nif __name__ == '__main__':\r\n main()\r\n"
<class 'bytes'>
由此可见,文件编码方式是Ascii,debug.py中的空格、换行等也会以字符的形式展现,如果有中文的话,中文会以十六进制的方式呈现,比如说“你好”(\xe4\xbd\xa0\xe5\xa5\xbd)。如果以'r'模式读取文件,结果又是怎样的呢?
def main():
pass
if __name__ == '__main__':
main()
没错,跟我们开头写进去的代码是一样的,这时候返回的结果是str形式的字符串。需要注意的是,chardet.detect()只能对bytes类型的字符串使用,否则会报错。
str和bytes之间的转换,需要用到解码和编码这两个概念。以下内容根据个人理解所写,如有出错,欢迎指出。
编码(encode)即是将我们所用str(一般来说,我们写的字符串都是str格式的,作为人类,我觉得还是str容易写点)以某一种编码方式转成机器能读懂的二进制数据格式(bytes)。解码(decode)则是相反的过程。
bytes --> decode('输入源文件的编码方式')--> str
str --> encode('以某种编码方式') --> bytes
注意解码和编码使用的对象。这个过程可以理解成上世纪发电报的过程。人们将通用语言,以某一种方式(比如说摩斯密码)转成另外一种格式,发送给对方,对方接收之后,必须再反过来转成通用语言才能理解。这就是编码和解码的过程。
言归正传,如果要转换文件的编码方式,那么就需要一个中间媒介。纵使编码方式不同,可能bytes对象会有所不同,但我们的通用语言却都是一致的。思路便是读取文件的bytes对象,然后解码成str,再以想要的编码方式(一般是utf-8)编码成bytes,最终写入原来的文件。
data_str = data_bytes.decode(chardet.detect(data_bytes)['encoding'])
print(data_str)
上面得到的结果,仍然是和以‘r’读取的方式一样。为什么不直接读取str?读取文件都有默认的编码方式,所以有可能直接读取str会因为编码方式的不同而出现乱码。
#以utf-8的编码格式转成bytes
data_utf = data_str.encode('utf-8')
通过这个指令可以得到utf-8编码的bytes,再将它写入覆盖源文件,即可完成转码。
作者注:编译器会将没有中文的py脚本识别为Ascii,所以通过转码最终也是会被识别成Ascii,不知道是不是系统为了节省内存空间的机制。这个目前我还没有找到解决方法,有解决方法再回来更改,望谅解。