字符编码
什么事字符编码?
什么是字符编码?
人类在与计算机交互时,用的都是人类能读懂的字符,如中文字符、英文字符、日文字符等,而计算机只能识别二进制。所以就产生了字符编码
'''
字符串类型、文本文件的内容都是由字符组成的,但凡涉及到字符的存取,都需要考虑字符编码的问题。
字符编码只跟文本数据和字符串有关系,他跟视频文件、音频文件无关。
'''
1、为什么要有字符编码?
因为计算机内部只认识0、1二进制
1.1、但是,我们现在在计算机上写的各种各样的字符,为什么都能正常显示?
字符编码:内部记录者字符和数字之间的对应关系。
Eg:
0 ---> a
1 ---->b
00 ---> aa
01----> ab
000 ----> aaa
001 -----> aab
010101010--->你好
字符编码发展史
1、一开始是由美国人发明的,所以当时计算机只能识别英文字符
# ASCII码表:内部记录了英文字符和数字至今的关系
# 一个英文字符对应1Bytes,1Bytes=8bit,8bit最多包含256个数字,可以对应256个字符,足够表示所有英文字符
2 ** 8 = 256
2、为了让计算机能够识别中文和英文,中国人定制了GBK
# GBK表的特点:
只有中文字符、英文字符与数字的一一对应关系
一个英文字符对应1Bytes
一个中文字符对应2Bytes
补充说明:
1Bytes=8bit,8bit最多包含256个数字,可以对应256个字符,足够表示所有英文字符
2Bytes=16bit,16bit最多包含65536个数字,可以对应65536个字符,足够表示所有中文字符
2.1、每个国家都各自的字符,为让计算机能够识别自己国家的字符外加英文字符,各个国家都制定了自己的字符编码表
# Shift_JIS表的特点:
1、只有日文字符、英文字符与数字的一一对应关系
# Euc-kr表的特点:
1、只有韩文字符、英文字符与数字的一一对应关系
3、unicode于1990年开始研发,1994年正式公布,具备两大特点:
# 存在所有语言中的所有字符与数字的一一对应关系,即兼容万国字符
# 与传统的字符编码的二进制数都有对应关系。
# 它的内部是统一使用两个字节保存字符或者更多字符
由于原来的英文字符是使用一个字节保存的,现在万国码使用了两个字节,所以就把资源浪费了一倍。
经过优化就推出来了utf-8编码(unicode的优化版本):
# 原来使用一个自己的英文字符,现在还使用一个字节保存
中文字符使用三个字节保存:即2的24次方
"""
最终得出结论:以后在使用字符编码的时候就使用utf8
"""
# 补充:
utf-8、utf-16、utf-32...、utf8mb4(存表情)
字符编码实操
1、如何解决乱码问题?
# 在写入的时候用的什么编码,打开的时候就用什么编码。
2、在Python解释其中有什么差异?
# 在Python2x中用的还是ASCII码表,所以没办法识别出来中文
解决办法:
# **-coding:utf-8-**
s = u'你好'
print s # 你好
'''在Python3x中字符编码用的都是utf - 8'''
3、编码和解码:
编码:就是把其他字符串类型转为二进制
str----->unicode----->0101001
ASCII---->GBK------>unicode----->utf8
解码:解码就是把二进制转为其他字符串的过程
编码:关键字(encode)
res = 'helloworld'
res1 = res.encode('utf8')
print(res1) # b'helloworld'
解码:关键字(decode)
res = 'helloworld'
res1 = res.encode('utf8')
print(res1) # b'helloworld'
res2 = res1.decode('utf8')
print(res2)
# 补充
s1 =b'hello123' # 只能是纯英文字符或数字
s2='hello123'.encode('utf8')
文件操作
1、为什么要使用代码操作文件?
# 当文件太多人工处理起来不方便的时候,就需要借助代码了。
2、如何操作文件?关键字(open、encoding、read)
2.1、打开文件
2.2、操作文件(读、写)
2.3、关闭文件(释放资源)
"""
在路径中如果出现了斜杠和字母连用的情况,为了不产生歧义,在路径的前面加一个r
r+绝对路径
"""
res = open('c.txt' , 'r' , encoding='utf8')
print(res) # <_io.TextIOWrapper name='c.txt' mode='r' encoding='cp936'>
print(res.read()) # 文件里面的内容
res.close() # 释放资源
# 方式二
with open('c.txt', 'r', encoding='utf8') as y:
print(y.read())
# 内部自动关闭close
文件操作模式
1、t模式
read里面写的数字代表字符个数
2、b模式
read里面写的数字代表字节的个数
Eg:
with open('a.txt','r',encoding='utf-8') as f:
data=f.read(3) # 读取3个字符
with open('a.txt','rb') as f:
data=f.read(3) # 读取3个Bytes
文件内的指针移动关键字(seek)
0模式
默认的模式,该模式代表指针移动的字节数是以文件开头为参照的(支持tb模式)
Eg:
with open('a.txt','rt',encoding='utf-8') as f:
f.seek(3,0) # 参照文件开头移动了3个字节
print(f.tell()) # 查看当前文件指针距离文件开头的位置,输出结果为3
print(f.read()) # 从第3个字节的位置读到文件末尾,输出结果为:你好
# 注意:由于在t模式下,会将读取的内容自动解码,所以必须保证读取的内容是一个完整中文数据,否则解码失败
with open('a.txt',mode='rb') as f:
f.seek(6,0)
print(f.read().decode('utf-8')) #输出结果为: 好
1模式
该模式代表指针移动的字节数是以当前所在位置为参照的(仅支持b模式)
Eg:
1模式的使用
with open('a.txt',mode='rb') as f:
f.seek(3,1) # 从当前位置往后移动3个字节,而此时的当前位置就是文件开头
print(f.tell()) # 输出结果为:3
f.seek(4,1) # 从当前位置往后移动4个字节,而此时的当前位置为3
print(f.tell()) # 输出结果为:7
2模式
该模式代表指针移动的字节数是以末尾位置为参照的(仅支持b模式)
Eg:
# 2模式的使用
with open('a.txt',mode='rb') as f:
f.seek(0,2) # 参照文件末尾移动0个字节, 即直接跳到文件末尾
print(f.tell()) # 输出结果为:9
f.seek(-3,2) # 参照文件末尾往前移动了3个字节
print(f.read().decode('utf-8')) # 输出结果为:好
文件的修改
1、文件的修改方式一
实现思路:将文件内容发一次性全部读入内存,然后在内存中修改完毕后再覆盖写回原文件
# 优点: 在文件修改过程中同一份数据只有一份
# 缺点: 会过多地占用内存
2、文件的修改方式二
# 实现思路:以读的方式打开原文件,以写的方式打开一个临时文件,一行行读取原文件内容,修改完后写入临时文件...,删掉原文件,将临时文件重命名原文件名# 优点: 不会占用过多的内存# 缺点: 在文件修改过程中同一份数据存了两份
Eg:
with open('a.txt', 'r', encoding='utf8') as f:
data = f.read()
print(data)
res = data.replace('kevin', 'tank')
print(res)
with open('a.txt', 'w', encoding='utf8') as f:
f.write(res)