文章目录
- 系列文章目录
- 字符编码
- 文件操作
- 文件其他常用操作
- 只读
- 只写
- 追加模式
- t与b的区别
- 可读可写
- r+t 模式
- w+t模式
- a+t模式
- 指针移动
- seek()函数
- 检测文件末尾新增的内容
- 修改文件的方式
- 修改文件的方式一
- 修改文件的方式二
- 避免乱码
字符编码
参考百度百科:
https://baike.baidu.com/item/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81/8446880?fr=aladdin
文件操作
'''
1 什么是文件
文件是操作系统为用户/应用程序提供的一种操作硬盘的抽象单位
2 为何要用文件
用户/应用程序对文件的读写操作会由操作系统转换成具体的硬盘操作
所以用户/应用程序可以通过简单的读\写文件来间接地控制复杂的硬盘的存取操作
实现将内存中的数据永久保存到硬盘中
user=input('>>>>: ') #user="小王"
3 如何用文件
文件操作的基本步骤:
f=open(...) #打开文件,拿到一个文件对象f,f就相当于一个遥控器,可以向操作系统发送指令
f.read() # 读写文件,向操作系统发送读写文件指令
f.close() # 关闭文件,回收操作系统的资源
上下文管理:
with open(...) as f:
pass
'''
# 绝对路径
f = open(r'/Users/jaidun/data/python_space/a.txt', encoding='utf-8')
print(f.read())
f.close()
# 相对路径
# 读取当前文件
f = open(r'a.txt', encoding='utf-8')
# ../相对路径
f = open(r'../a.txt', encoding='utf-8')
print(f.read())
f.close()
# # 强调:一定要在程序结束前关闭打开的文件
# 可能会忘记
# # f.close()
# print(f.read())
# 上下文管理:with
# with open(...) as f:
# pass
# 可以自动关闭文件
with open(r'a.txt', encoding='utf-8')as f:
print(f.read())
# print(f.read())
文件其他常用操作
一 文件的打开模式
r: 只读模式(默认的)
w: 只写模式
a: 只追加写模式
二 控制读写文件单位的方式(必须与r\w\a连用)
t : 文本模式(默认的),一定要指定encoding参数
优点: 操作系统会将硬盘中二进制数字解码成unicode然后返回
强调:只针对文本文件有效
b: 二进制模式,一定不能指定encoding参数
优点:可以网络直接传输
只读
#一 r: 只读模式(默认的)
# 1 当文件不存时,会报错
# 2 当文件存在时,文件指针指向文件的开头
with open('a.txt',mode='rt',encoding='utf-8')as f:
res1=f.read()
print('111>>>',res1)
# # 第一次读完了
res2 = f.read()
print('222>>>', res2)
# 判断rt模块可读
print(f.readable())
# # 判断rt模式不可写
print(f.writable())
# read 文件太大不好
print(f.readline(),end='')
# # #文件里面有换行符 print自带换行符\n
print(f.readline())
# for循环遍历文件对象
for line in f:
print(line,end='')
L = []
for line in f:
L.append(line)
print(L)
# 一行代码搞定
print(f.readlines())
只写
# 二 wt: 只写模式
# 1 当文件不存时,新建一个空文档(无则创建)
# with open('b.txt',mode='wt',encoding='utf-8')as f:
# pass
# 2 当文件存在时,清空文件内容,文件指针跑到文件的开头(有则清空)
with open('b.txt',mode='wt',encoding='utf-8')as f:
# 全部清空
# 下面写我们想要的内容
# 不能读
print(f.readable())
# 可以写
print(f.writable())
# f.read()
# 记得要写换行符
# 把之前的内容覆盖了
# f.write(字符串)
f.write('小王\n')
f.write('大王\n')
f.write('小戴\n')
# 一次性写多行
f.write('111\n2222\n3333\n')
# 把列表内容一行行写入
info = ['大海\n','大海\n','大海\n']
for line in info:
f.write(line)
# 一行代码搞定
# writelines(列表)
f.writelines(info)
追加模式
# 三 at: 只追加写模式
# 1 当文件不存时,新建一个空文档,文件指针跑到文件的末尾(开头就是末尾)
# with open('c.txt',mode='at',encoding='utf-8')as f:
# pass
# 2 当文件存在时,文件指针跑到文件的末尾
with open('c.txt',mode='at',encoding='utf-8')as f:
# 不能读
print(f.readable())
# 能写
print(f.writable())
f.write('小王老师\n')
f.write('小戴老师\n')
f.write('小周老师\n')
with open('c.txt',mode='at',encoding='utf-8')as f:
# 不能读
print(f.readable())
# 能写
print(f.writable())
f.write('戴老师\n')
f.write('杨老师\n')
f.write('付老师\n')
w模式和a模式的区别
wt模式
在文件打开不关闭的情况下,连续的写入,
下一次写入一定是基于上一次写入指针的位置而继续的
a模式关闭了下次打开是在文件末尾写,所以不会覆盖之前的内容
t与b的区别
二 控制读写文件单位的方式(必须与r\w\a连用)
t : 文本模式(默认的),一定要指定encoding参数
优点: 操作系统会将硬盘中二进制数字解码成unicode然后返回
强调:只针对文本文件有效
b: 二进制模式,一定不能指定encoding参数
优点:可以直接网络传输
# 只能对文本文件操作 t 模式局限性
# 二进制文件 b 模式
# 图片和视频
with open('1.jpeg', mode='rb', )as f:
data = f.read()
print(data)
print(type(data))
with open('2.jpeg', mode='wb')as f1:
f1.write(data)
# 用b模式,也可以对文本文件操作,但是要解码
# decode 二进制解码成字符
# encode 字符编码成二进制
# 解码 读的时候转换成字符
with open('b模式.txt', mode='rb')as f:
data = f.read()
print(data)
print(data.decode('utf-8'))
# 编码 写的时候把字符转换成二进制写入
with open('wb模式.txt', mode='wb')as f:
f.write('小红\n'.encode('utf-8'))
f.write('小王\n'.encode('utf-8'))
f.write('小戴\n'.encode('utf-8'))
可读可写
r+t 模式
1 当文件不存时,会报错
2 当文件存在时,文件指针指向文件的开头
3 多了个末尾写
with open('可读可写r+t模式.txt', mode='r+t', encoding='utf-8')as f:
print(f.readable())
print(f.writable())
msg = f.readline()
print(msg)
f.write('xxxxxxxx')
w+t模式
1 当文件不存时,新建一个空文档(无则创建)
2 当文件存在时,清空文件内容,文件指针跑到文件的开头(有则清空)
with open('可读可写w+t模式.txt', mode='w+t', encoding='utf-8')as f:
print(f.readable())
print(f.writable())
f.write('aaaaaaaa\n')
f.write('bbbbbbbb\n')
# 指针移动seek(移动的字节数,开头开始0)
# 从开头开始移动0
f.seek(0, 0)
print(f.readline())
f.write('cccccccc\n')
a+t模式
第二次打开时候也是在末尾写
with open('可读可写a+t模式.txt',mode='a+t',encoding='utf-8')as f:
print(f.readable())
print(f.writable())
f.write('aaaaaaaa\n')
f.write('bbbbbbbb\n')
# 指针移动seek(移动的字节数,开头开始0)
# 从开头开始移动0
f.seek(0,0)
print(f.readline())
f.write('cccccccc\n')
# 图片和视频用不上
# r+b w+b a+b 规律和r+t w+t a+t
指针移动
seek()函数
文件内指针移动
t模式下的read(n),n代表的字符的个数
b模式文件内指针的移动都是以字节为单位指针操作
f.seek(offset,whence)有两个参数:
offset: 代表控制指针移动的字节数
whence: 代表参照什么位置进行移动
whence = 0: 参照文件开头(默认的),特殊???,可以在t和b模式下使用
whence = 1: 参照当前所在的位置,必须在b模式下用
whence = 2: 参照文件末尾,必须在b模式下用
# t模式
# with open('指针移动.txt',mode='rt',encoding='utf-8')as f:
# print(f.read(1))
# print(f.read(1))
# print(f.read(1))
# b模式
# with open('指针移动.txt', mode='rb')as f:
# # 2个16进制是2**4 2**8
# # 三分之一个汉字
# print(f.read(1).decode('utf-8'))
# print(f.read(1).decode('utf-8'))
# print(f.read(3).decode('utf-8'))
# print(f.read(3).decode('utf-8'))
# print(f.read(3).decode('utf-8'))
# 指针操作
# f.seek(offset,whence)有两个参数:
# offset: 代表控制指针移动的字节数
# whence: 代表参照什么位置进行移动
# whence = 0: 参照文件开头(默认的),特殊???,可以在t和b模式下使用
# whence = 1: 参照当前所在的位置,必须在b模式下用
# whence = 2: 参照文件末尾,必须在b模式下用
# t模式 按照字符算
with open('seek.txt',mode='rt',encoding='utf-8')as f:
f.seek(2,0)
print(f.read(1))
# b模式 移动的字节数 读的也是字节数
with open('seek.txt',mode='rb')as f:
f.seek(5,0)
print(f.read(3).decode('utf-8'))
with open('seek.txt',mode='rb')as f:
msg = f.read(5)
# 当前光标所在的字节数
print(f.tell())
f.seek(3,1)
print(f.read(3).decode('utf-8'))
with open('seek.txt',mode='rb')as f:
f.seek(0,2)
print(f.tell())
f.seek(-3,2)
print(f.read(3).decode('utf-8'))
检测文件末尾新增的内容
with open('历史.txt',mode='rb')as f:
f.seek(0,2)
while True:
line=f.readline()
# 如果是0个bytes意味着光标在最后
# 没有关闭这个文件操作
if len(line) != 0:
print(line.decode('utf-8'),end= '')
修改文件的方式
修改文件的方式一
1 将文件内容由硬盘全部读入内存
2 在内存中完成修改
3 将内存中修改后的结果覆盖写回硬盘
with open('文件修改.txt', mode='rt', encoding='utf-8')as f:
all_data = f.read()
# # 读出来的数据已经存到all_data变量里面的了
with open('文件修改.txt', mode='wt', encoding='utf-8')as f1:
f1.write(all_data.replace('小王', '大王'))
修改文件的方式二
1 以读的方式打开源文件,以写的方式打开一个临时文件
2 从源文件中每读一样内容修改完毕后写入临时文件,直到源文件读取完毕
3 删掉源文件,将临时文件重命名为源文件名
import os
with open('文件修改二.txt',mode='rt',encoding='utf-8')as read_f,open('临时文件.txt',mode='wt',encoding='utf-8') as write_f:
for line in read_f:
write_f.write(line.replace('小戴','小杨'))
# 文件修改二删除
os.remove('文件修改二.txt')
# # 临时文件.txt 改成 文件修改二
os.rename('临时文件.txt','文件修改二.txt')
方式一:
优点: 在文件修改的过程中硬盘上始终一份数据
缺点: 占用内存过多,不适用于大文件方式二:
优点: 同一时刻在内存中只存在源文件的一行内容,不会过多地占用内存
缺点: 在文件修改的过程中会出现源文件与临时文件共存,硬盘上同一时刻会有两份数据,即在修改的过程中会过多的占用硬盘,
避免乱码
# 天生我才必有用
# 日语
with open('text1.txt', mode='w', encoding='shift_jis')as f1:
f1.write('生まれながらにしてわたくし私はかならず必ずやく役にたつ立つ')
# with open('text1.txt', mode='r', encoding='utf-8')as f1:
# a = f1.read()
# print(a)
# 英文
with open('text2.txt', mode='w', encoding='shift_jis')as f1:
f1.write('I believe')
with open('text2.txt', mode='r', encoding='utf-8')as f2:
a = f2.read()
print(a)
!!!总结非常重要的两点!!!
1、保证不乱码的核心法则就是,字符按照什么标准而编码的,
就要按照什么标准解码,此处的标准指的就是字符编码2、在内存中写的所有字符,一视同仁,都是unicode编码,比如我们打开编辑器,
输入一个“你”,我们并不能说“你”就是一个汉字,此时它仅仅只是一个符号,
该符号可能很多国家都在使用,根据我们使用的输入法不同这个字的样式可能也不太一样。
只有在我们往硬盘保存或者基于网络传输时,
才能确定”你“到底是一个汉字,还是一个日本字,这就是unicode转换成其他编码格式的过程了