目录
不同字符编码间的转换
文件操作
打开文件
关闭文件
写文件
读文件
二进制模式操作文件
练习题-全局文本检索替换
不同字符编码间的转换
windows 系统的默认编码是 GBK, 如果你把⼀段在 windows 系统上⽤ gbk 编码的字符发
送到 mac 电脑 上, mac 默认编码是 utf-8, 那这段文字是乱码显示的。 如何实现在 mac 上正常显示这段 gbk文本呢?
编码与解码
1.把任意编码转换成unicode的过程叫做解码
>>> s="卿云"
>>> s="卿云"#unicode格式
>>> s.encode("utf-8") #将其编码成utf-8
b'\xe5\x8d\xbf\xe4\xba\x91'
2.把unicode转换成的任意编码过程叫做编码
>>> s
'卿云'
>>> s.encode("utf-8").decode("utf-8")#把utf-8编码的字符在转化成unicode
'卿云'>>> s
'卿云'
>>> s.encode("utf-8") #将其编码成utf-8
b'\xe5\x8d\xbf\xe4\xba\x91
#会变成bytes字节格式,bytes字节类型是用16进制表示的,像\xe5这样两个16进制数是代表一个字节(因为一个16进制数占4位)
字节类型到底是什么
字节类型其实就是二进制数,只不过为了易于理解,常用16进制数表示。
文件操作
打开文件
f=open(file='C:/Users/Administrator/Desktop/zz.txt',mode='w',encoding='utf-8')
追加模式
f=open(file='C:/Users/Administrator/Desktop/zz.txt',mode='a') f.write("zz 202018085\n") f.close() #保存并关闭
关闭文件
f.close() #保存并关闭
写文件
file.write(s)
f=open(file='C:/Users/Administrator/Desktop/zz.txt',mode='w') #在文件夹中复制地址时,文件夹中的地址是用 \ 来分隔不同文件夹的,而Python识别地址时只能识别用 / 分隔的地址。
f.write("我叫卿云\n") #写文件
f.write("我喜欢打乒乓球\n") #写文件
f.close() #保存并关闭
file.writelines(s)
file=open('example.txt','w',encoding='utf-8')
# 写入多行内容
lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
file.writelines(lines)
读文件
f=open(file='C:/Users/Administrator/Desktop/zz.txt',mode='r')
print(f.readline())#读一行
print('-----分隔符-----')
data=f.read()
print(data)
f.close() #保存并关闭
结果
卿云 202018081
-----分隔符-----
文竹 202018082
循环文件
f = open(file='C:/Users/qingyun/Desktop/兼职⽩领学⽣空姐模特护⼠联系⽅式.txt',encoding="utf-8",mode='r')
for line in f:
line = line.split()
name,addr,height,weight,phone = line
height = int(height)
weight = int(weight)
if height > 170 and weight <= 50: # 只打印身⾼>170 and 体᯿<=50的
print(line)
f.close()
结果
['⻢纤⽻', '深圳', '173', '50', '13744234523']
['罗梦⽵', '北京', '175', '49', '18623423421']
['叶梓萱', '上海', '171', '49', '18042432324']
二进制模式操作文件
上面操作的只是文本文件 ,但是如果遇到视频呀、图片呀,你直接打开的话会报错是因为,open() 有个 encoding 参数 , 默认是 None, 是用来告诉解释器,要操作的这个文件 是什么编码。 不填的话,就⽤解释器默认编码,即utf-8 。
如果你是⼀个 gbk 编码的文件 ,就必须指定 encoding=gbk
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None,
closefd=True, opener=None)f = open("gbk_file",encoding="gbk")
for line in f:
print(line)
但是像图片、视频,是有自己特殊的编码的,而非什么 unicode\utf-8 这样的文本编码 。 所以要操作这样的文件 ,你用utf-8 什么的去解,自然会报错。
如何处理图⽚、视频⽂件呢?
可以用 2 进制模式打开文件
rb 2 进制只读模式
wb 2 进制创建模式,若⽂件已存在,则覆盖旧文件
ab 2 进制追加模式,新数据会写到文件末尾
这样,你读出来的数据,就是 bytes 字节类型了,当然写进去的也必须是 bytes 格式了
f = open("gbk_file2","wb")
f.write("哈".encode("gbk") ) # 写⼊的⽂本要⽤字节类型
练习题-全局文本检索替换
写⼀个脚本,允许⽤户按以下⽅式执⾏时,即可以对指定⽂件内容进⾏全局替换,且替换完毕后打印替换了多少处内容
写完后的脚本调用方式:
python your_script.py old_str new_str filenameimport sys
old_str=sys.argv[1]
new_str=sys.argv[2]
filename=sys.argv[3]
#1. load into ram
f=open(filename,"r+")
data=f.read()
#2. count and replace
old_str_count=data.count(old_str)
new_data=data.replace(old_str,new_str)
#3. clear old filename
f.seek(0)
f.truncate()
#4.save new data into file
f.write(new_data)
print("成功")
print(f'''成功替换字符'{old_str}' to '{new_str}',共{old_str_count}处...''')
编码方式
二进制运算
计算机是靠电流驱动的,科学家们是如何做到让电流能理解数字、文字、图片等人类语言的呢? 科学家发现,可以通过控制电压把电流分成高电压、低电压, 高电压可以代表⼀种状态,低电压又可代 表另一状态。这样计算机就可以识别2种状态了。 就像⼀个灯泡,开灯可以代表1,关灯可以代表0,就 是2种状态 。如果多个灯泡的组合,就可以表达更多的值啦。这跟数学⾥的⼀个叫⼆进制的东东很像, ⼆进制只有0和1两个数,想表达更⼤的值 就往左补位,多个0101010就可以表达更⼤的值 啦。 ⼆进制 是逢2进1, 跟我们用的⼗进制逢10进1⼀个原理。 于是科学家们,就⽤2进制做为计算机可识别的最底层语言啦。
字符编码
我们自己强行约定了⼀个表,把文字 和数字对应上,这张表就相当于翻译,我们可以拿着⼀个数字来对比对应表找到相应的文字,反之亦然。
ASCII编码
⼀个空格对应的数字是0 翻译成⼆进制就是0(注意字符'0'和整数0是不同的) ⼀个对勾√对应的数字是251 翻译成⼆进制就是11111011
假如我们要打印两个空格⼀个对勾 写作二进制就应该是 0011111011, 但是问题来了,我们怎么知道从哪儿到哪儿是⼀个字符呢?
正是由于这些字符串长的长,短的短,写在⼀起让我们难以分清每⼀个字符的起⽌位置,所以聪明的⼈ 类就想出了⼀个解决办法,既然⼀共就这255个字符,那最⻓的也不过是11111111八位,不如我们就把所有的二进制都转换成8位的,不足的用0来替换。 这样⼀来,刚刚的两个空格⼀个对勾就写作000000000000000011111011,读取的时候只要每次读8个 字符就能知道每个字符的二进制值啦。
计算机容量单位
bit 位,计算机中最⼩的表示单位 8bit = 1bytes 字节,最⼩的存储单位,1bytes缩写为1B 1KB=1024B 1MB=1024KB 1GB=1024MB # 电影 1TB=1024GB # 移动硬盘 1PB=1024TB 1EB=1024PB 1ZB=1024EB 1YB=1024ZB 1BB=1024YB
GB2312 & GBK
英文问题是解决了, 我们中文如何显示呢? 美国佬设计ASSCII码的时候应该是没考虑中国⼈有⼀天也能用上电脑, 所以根本没考虑中文的问题,上世界80年代,电脑进入中国,把砖家们难倒了,ASSCII只能存256个字符,我常用汉字就几千个,怎么玩???勒紧裤腰带还苏联贷款的时候我们都挺过来啦,这点小事难不到我们, 既然美帝的ASCII不支持中文,那我们自己搞张编码表不就⾏了, 于是我们1980年设计出了GB2312编码表,长成下面的样子。⼀共存了6763个汉字。
这个表格比较大,像上面的⼀块块的文字区域有72个,这导致通过⼀个字节是没办法表示⼀个汉字的 (因为一个字节最多允许256个字符变种,你现在6千多个,只能2个字节啦,2**16=65535个变种)。 有了gb2312,我们就能愉快的写中文啦。
如何区别连在一起的2个字节是代表2个英文字母,还是⼀个中文汉字呢? 中国⼈如此聪明,如 果2个字节连在⼀起,且每个字节的第1位(也就是相当于128的那个2进制位)如果是1,就代表这是个中文,这个首位是128的字节被称为⾼字节。 也就是2个高字节连在⼀起,必然就是⼀个中文。
⼀ 直到现在,我们的windows电脑中文版本的编码就是GBK.
编码战国时代
很多国家都有自己的编码
解决乱码:
1.中国电脑 上装日本 shift_jis
2. 让日本 游戏厂商,用gbk编码
中国人在搞自己编码的同时,世界上其它非英语国家也得⽤电脑呀,于是都搞出了自己的编码,你可以 想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩⽂编到Euc-kr里, 各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。之前你从玩个日本游戏,往自己电脑上⼀装,就显示乱码了。
这么乱极大了阻碍了不同国家的信息传递,于是联合国出面,发誓要解决这个混乱局⾯。
因此,Unicode应运而生。Unicode把所有语言都统一到⼀套编码里,这样就不会再有乱码问题了。
Unicode和UTF-8
Unicode 2-4字节 已经收录136690个字符,并还在⼀直不断扩张中…Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。
Unicode有2个特点:
1. 支持全球所有语言
2. 可以跟各种语言的编码自由转换,也就是说,即使你gbk编码的文字 ,想转成unicode很容易。 为何unicode可以跟其它语言互相转换呢? 因为有跟所有语言都有对应关系哈,这样做的好处是可以让 那些已经用gbk或其它编码写好的软件容易的转unicode编码 ,利于unicode的推广。 下图就是成unicode跟中文编码的对应关系新的问题又出现了:如果统一 成 Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,⽤Unicode编码⽐ASCII编码需要多⼀倍的存储空间,由于计算机的内存比较大,并且 字符串在内容中表示时也不会特别大,所以内容可以使用unicode来处理,但是存储和网络传输时⼀般 数据都会非常多,那么增加1倍将是无法容忍的!!! 为了解决存储和网络传输的问题,出现了Unicode Transformation Format,学术名UTF,即:对
unicode字符进⾏转换,以便于在存储和⽹络传输时可以节省空间!
UTF-8: 使⽤1、2、3、4个字节表示所有字符;优先使⽤1个字节、⽆法满⾜则使增加⼀个字节,
最多4个字节。英⽂占1个字节、欧洲语系占2个、东亚占3个,其它及特殊字符占4个
UTF-16: 使⽤2、4个字节表示所有字符;优先使⽤2个字节,否则使⽤4个字节表示。
UTF-32: 使⽤4个字节表示所有字符;
总结:UTF 是为unicode编码 设计 的⼀种 在存储 和传输时节省空间的编码⽅案。
如果你要传输的⽂本包含⼤量英⽂字符,⽤UTF-8编码就能节省空间:
UTF-8编码有⼀个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编 码的⼀部分,所以,⼤量只⽀持ASCII编码的历史遗留软件可以在UTF-8编码下继续⼯作。
搞清楚了ASCII、Unicode和UTF-8的关系,我们就可以总结⼀下现在计算机系统通⽤的字符编码⼯作⽅式:
在计算机内存中,统⼀使⽤Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编 码。 ⽤记事本编辑的时候,从⽂件读取的UTF-8字符被转换为Unicode字符到内存⾥,编辑完成后,保存的 时候再把Unicode转换为UTF-8保存到⽂件