字符编码与文件处理

字符编码

引入

字符串类型、文本类型都是由字符组成的,但凡涉及到字符的存取,都需要考虑字符编码的问题。
所有软件都是运行硬件之上,与运行软件相关三大核心硬件为CPU、内存、硬盘,我们需要知道的是:
1、运行软件前,软件的代码及相关数据都是存放于硬盘中
2、任何软件启动都是将数据从硬盘中读入内存,然后CPU从内存中读取指令并执行
3、软件运行过程中产生数据最先都是存放于内存中,若想永久保存产生的数据,则需要将数据由内存写入到硬盘中

什么是字符编码

人类与计算机交互时,用的都是人类能够读懂的字符,如中文字符,英文字符等,而计算机只能识别二进制数,二进制数即由0和1组成的数字,
字符编码中的编码指的是翻译或者转换的意思,即将人能理解的字符翻译成计算机能识别的数字

字符编码的发展史

阶段一
现代计算机起源于美国,所以最先考虑仅仅是让计算机识别英文字符,于是诞生了ASCII表

阶段二
为让计算机能够识别自己国家的字符外加英文字符,各个国家都制定了自己的字符编码表
中国定制了GBK,特点只有中文字符、英文字符与数字的一一对应关系
日本定制了Shift_JIS,特点只有日文字符、英文字符与数字的一一对应关系
韩国定制了Euc-kr,特点只有韩文字符、英文字符与数字的一一对应关系

阶段三
希望计算机允许我们输入万国字符均可识别、不乱码定制一个兼容万国字符的编码表
即unicode,特点存在所有语言中的所有字符与数字的一一对应关系,即兼容万国字符,unicode码只在内存中起作用

阶段四
由于unicode固定使用两个字节来存储一个字符,如果多国字符中包含大量的英文字符时,使用unicode格式存放会额外占用一倍空间,当我们由内存写入硬盘时会额外耗费一倍的时间,所以将内存中的unicode二进制写入硬盘或者基于网络传输时必须将其转换成一种精简的格式,这种格式即utf-8(全称Unicode Transformation Format,即unicode的转换格式)

编码与解码

将人类能够读懂的语言转为计算机能够读懂的语言,把字符串转为二进制的过程,都称为编码encode

将计算机能够读懂的语言转为人类能够读懂的语言,把二进制转为字符串的过程,都称为解码decode

  • 使用
ss = '你们好,我是小漂亮'
#编码
e=ss.encode('utf8')#参数指定格式
print(e)#b'\xe4\xbd\xa0\xe4\xbb\xac\xe5\xa5\xbd\xef\xbc\x8c\xe6\x88\x91\xe6\x98\xaf\xe5\xb0\x8f\xe6\xbc\x82\xe4\xba\xae'
#解码
d=e.decode('utf8')#参数指定格式
print(d)#你们好,我是小漂亮
'''总结:用什么编码格式('utf8'),那么就要用什么解码格式('utf8')'''

  • 如何防止乱码
我们学习字符编码就是为了存取字符时不发生乱码问题:
1. 保证存的时候不乱:在由内存写入硬盘时,必须将编码格式设置为支持所输入字符的编码格式
2. 保证存的时候不乱:在由硬盘读入内存时,必须采用与写入硬盘时相同的编码格式

文件处理

引入

应用程序运行过程中产生的数据最先都是存放于内存中的,若想永久保存下来,必须要保存于硬盘中。应用程序若想操作硬件必须通过操作系统,而文件就是操作系统提供给应用程序来操作硬盘的虚拟概念,用户或应用程序对文件的操作,就是向操作系统发起调用,然后由操作系统完成对硬盘的具体操作。

文件操作三步骤

  • 打开文件
  • 操作文件
  • 关闭文件
#方式一
f=open('a.txt','r',encoding='utf8')#打开文件,由应用程序向操作系统发起系统调用open(...),操作系统打开该文件
print(f.read())#调用文件对象下的读/写方法,会被操作系统转换为读/写硬盘的操作
f.close()#向操作系统发起关闭文件的请求,回收系统资源
#需手动添加关闭文件
#方式二
with open('a.txt','r',encoding='utf8') as f1:
print(f1.read())
#with上下文管理器可自动关闭文件

文件的读写内容模式

  • t模式
1. 只能操作文本文件
2. 只能操作字符串或者字节单位
3. rt wt at t可以省略不写
=r =w =a
4. encoding参数必须写
with open('b.txt', 'wb') as f:
s = '你好'
f.write(s.encode('utf8'))#字符串转字节编码
with open('b.txt', 'rb') as f:#b模式写,必须b模式读
print(f.read().decode('utf8'))#字节转字符串解码
  • b模式:二进制
1. 能操作任何的文件数据类型,eg:文本,视频,音频...
2. 写法:rb ab wb 此时的b不能省略
3. encoding参数一定不写
4. 操作数据以字节为单位不能字符串
with open('b.txt', 'wb') as f:
s = '你好'
f.write(s.encode('utf8'))

文件的读写操作模式

r:只读
w:只写
a:只追加写

  • r模式使用
# 文件路径不存在,直接报错,文件存在将内容读取
with open(r'a.txt', 'r', encoding='utf-8') as f:
print(f.read())
  • w模式使用
#第一种情况 文件路径不存在,会新建一个文件出来
with open('b.txt', 'w', encoding='utf-8') as f:
pass
#第二种情况 文件路径存在,会先清空文件中的原内容,再进行写内容
with open('a.txt', 'w', encoding='utf-8') as f:
f.write('hello\n')
f.write('word\n')
f.write(str(123))
#强调:
# 1 连续的写入,不加\n那么后写的内容一定跟在前写内容的后面
# 2 如果重新以w模式打开文件,则会清空文件内容
# 3 写的数据必须是字符串类型或bytes类型
  • a模式使用
#第一种情况 文件路径不存在的时候,会新建一个文件出来
#第二种情况 文件路径存在,不会清空原来的内容,在原内容基础上追加新内容
with open('a.txt', 'a', encoding='utf-8') as f:
f.write('higirl\n')
  • +模式的使用(了解)
# r+ w+ a+ :可读可写
#在平时工作中,我们只单纯使用r/w/a,要么只读,要么只写,一般不用可读可写的模式

文件操作方法

  • 读方法
f.read()读取所有内容,执行完该操作后,指针会移动到文件末尾
f.readline()读取一行内容,指针移动到第二行首部
f.readlines()读取每一行数据然后组装成列表返回 ['', '']
f.readable()是否可读
with open(r'a.txt', 'r', encoding='utf-8') as f:
# print(f.read()) # 一次性读取文件内所有的数据
'''一次性读取文件所有的数据就会存在漏洞:导致内存溢出'''
# print(f.readline()) # 一次读取一行
# print(f.readable()) # True
# print(f.readlines()) # ['你好世界\n', '你好世界\n', '你好世界\n']
'''把文件内的一行一行数据组装成列表元素返回,注意末尾的换行符'''
a.txt内容:世界你好
#t模式
with open('a.txt', 'r',encoding='utf8') as f:
print(f.read(3))#世界你#数字代表字符个数
#b模式
with open('a.txt', 'rb') as f:
print(f.read(3))#b'\xe4\xb8\x96'
print(f.read(3).decode('utf-8')) #世
"""总结:
1. t模式
read()里面的数字代表的是读取字符的个数
2. b模式
read()里面的数字代表的是一个字节,如果文件里面是中文,因而一个中文字符是3个字节,那么read()里面的参数必须为3的倍数,否则报错
"""
  • 写方法
f.write()一次性写入数据
f.writelines以列表的形式写入数据 ['','']
f.writable()是否可写
with open('a.txt', 'w', encoding='utf-8') as f:
# f.write('hello\n')
# f.write('hello\n')
# f.write('hello\n')
# print(f.writable()) # True
# print(f.readable()) # False
# print(f.writelines(['你好世界\n', '你好世界2\n', '你好世界3\n']))
pass
''' 多段一起write时,如果不使用分隔符\n分割,会都在一行里面,不会帮你自动分割,这时我们使用\n分隔符分割段'''
  • 了解
with open('a.txt', 'w', encoding='utf-8') as f:
f.write('hello')
f.flush() # 把内存中得数据立刻刷到硬盘中

文件操作优化

针对文件读操作可能存在内存溢出的可能,以后读取文件数据的时候,使用for循环去一行一行的读取,避免出现内存溢出的情况

with open('a.txt', 'r', encoding='utf-8') as f:
print(f.read())
for line in f:#文件句柄f支持for循环
print(line) # 一次代码一行数据

文件指针的移动

若想读取文件某一特定位置的数据,则则需要用f.seek方法主动控制文件内指针的移动

f.seek(offset,whence)
1. offset参数指针移动的字节数
如果是整数,从左往右读取
如果是负数,从右往左读取
2. whence参数模式控制
0: 默认的模式,该模式代表指针移动的字节数是以文件开头为参照的(支持t、b模式)
1: 该模式代表指针移动的字节数是以当前所在的位置为参照的(只用于b模式)
2: 该模式代表指针移动的字节数是以文件末尾的位置为参照的(只用于b模式)
# 强调:其中0模式可以在t或者b模式使用,而1跟2模式只能在b模式下用
with open('a.txt', 'rb') as f:
f.seek(3, 0)# 参照文件开头移动了3个字节
f.seek(4,1) # 从当前位置往后移动4个字节
f.seek(0,2)# 参照文件末尾移动0个字节
f.seek(-3,2)# 参照文件末尾往前移动了3个字节
print(f.tell()) #告知指标当前所在位置
print(f.read().decode('utf-8'))

文件的修改

方式一:
# 1. 读取b.txt文件数据
with open('b.txt', 'r', encoding='utf-8') as f:
data = f.read()
print(data) # kevin kevin kevin kevin say hello world
new_data = data.replace('kevin', 'jack')
# 2. 把新的数据再次写入文件
with open('b.txt', 'w', encoding='utf-8') as f1:
f1.write(new_data)
方式二:
"先读取源文件 再使用字符串内置方法替换数据,再次把替换后的数据写入文件中"
import os
with open('a.txt','rt',encoding='utf-8') as read_f:
with open('b.txt',mode='wt',encoding='utf-8') as wrife_f:
for line in read_f:
wrife_f.write(line.replace('SB','kevin'))
os.remove('a.txt') # 删除源文件
os.rename('b.txt','a.txt')
posted @   爆炸小龙虾  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示