今日内容
1.什么是文件
2.为何用文件
3.如何用文件
4.文件操作补
5.常用方法
6.文件内指针的移动
7.with的使用
4. 文件操作
4.1 主模式
r:只读模式L(默认)
当文件不存在时,会报错
当文件存在时,文件指针指向文件的开头
w:只写模式
当文件不存在时,新建一个空文档
当文件存在时,清空文件内容,文件指针跑到文件的开头
info = ['egon:123\n','alex:456\n','lxx:lxx123']
f.writelines(info) #将列表里面的数据,一行行的写进去(自动换行)
a:追加 写模式
当文件不存在时,新建一个空文档,文件指针跑到文件的末尾
当文件存在时,文件指针跑到文件的末尾
在文件打开不关闭的情况下,连续的写入,下一次写入一定是基于上一次写入指针位置而继续的
f.write()
f.writelines()
4.2 文件操作从模式(必须与r/w/a连用
t:文本模式(默认的),一定指定encoding参数
优点:操作系统会将硬盘中的二进制数字解码成Unicode然后返回
强调:只针对文本文件有效
b:二进制模式:一定不能指定encoding参数
优点:
+:可读可写
r+: 不会创建文件的可读可写
w+:创建清空文件的可读可写
a+:创建不清空文件(追加)的可读可写
rb: 二进制读
wb:创建清空文件的二进制写
ab: 创建不清空文件(追加)的二进制写
rb+ | wb+ | ab+
# ps: x:写模式,创建文件,如果文件以存在,就抛异常
with open('000.txt', 'x', encoding='utf-8') as f:
pass
4.3 案例
# 需求:
# 1.完成文本类型的文件复制:1.txt => 11.txt
r = open('1.txt', 'r', encoding='utf-8')
w = open('11.txt', 'w', encoding='utf-8')
for line in r: # 遍历就是一行一行读 取读文件的流
w.write(line)
w.flush()
w.close()
r.close()
5. 常用方法
#掌握
f.read() #读取所有内容,光标移动到文件末尾
f.readline() #读取一行内容,光标移动到第二行首部
f.readlines() #读取每一行内容,存放于列表中
f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符
f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333\n','444\n']) #文件模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
f.flush() #立刻将文件内容从内存刷新到硬盘
#了解
f.readable() #文件是否可读
f.writable() #文件是否可读
6.2 案例: 游标操作
# 方法:seek(偏移量, 偏移位置)
# 偏移量:移动的字节数,负数是结合模式1,2往前偏移
# 偏移位置:
# -- 0 - 从文件开始位置开始偏移 | 1 - 从当前游标位置开始偏移 | 2 - 从文件末尾开始偏移
# b'你好1234567890'
#游标读
with open('source.txt', 'rb') as f:
d1 = f.read(11)
print(d1)
# print(d1.decode('utf-8'))
# 当前游标的位置
print(f.tell())
# 游标操作 - 从末尾位置开始
f.seek(-3, 2)
d2 = f.read()
print(d2.decode('utf-8')) # 890
# 游标操作 - 从当前位置开始
f.seek(-3, 1)
d2 = f.read()
# print(d2.decode('utf-8')) # 34567890
# 游标操作 - 从头开始
f.seek(3, 0)
d2 = f.read()
# print(d2)
print(d2.decode('utf-8')) # 好1234567890
游标写:会覆盖书写
with open('source.txt', 'rb+') as f:
f.seek(11)
# print(f.read())
f.write(b'000')
6.3 百度网盘秒传分析
# 方法:seek(偏移量, 偏移位置)
# 偏移量:移动的字节数,负数是结合模式1,2往前偏移
# 偏移位置:
# -- 0 - 从文件开始位置开始偏移 | 1 - 从当前游标位置开始偏移 | 2 - 从文件末尾开始偏移
# b'你好1234567890'
#游标读
with open('source.txt', 'rb') as f:
d1 = f.read(11)
print(d1)
# print(d1.decode('utf-8'))
# 当前游标的位置
print(f.tell())
# 游标操作 - 从末尾位置开始
f.seek(-3, 2)
d2 = f.read()
print(d2.decode('utf-8')) # 890
# 游标操作 - 从当前位置开始
f.seek(-3, 1)
d2 = f.read()
# print(d2.decode('utf-8')) # 34567890
# 游标操作 - 从头开始
f.seek(3, 0)
d2 = f.read()
# print(d2)
print(d2.decode('utf-8')) # 好1234567890
游标写:会覆盖书写
with open('source.txt', 'rb+') as f:
f.seek(11)
# print(f.read())
f.write(b'000')
6.3 百度网盘秒传分析
# 案例
#以图片为例,按照一定规则从文件中摘取一些数据,
#加工后通过与服务器端数据进行对比,如果数据一样则不需要传输,
#直接将服务器内文件地址给用户即可
with open('001.png', 'rb') as f:
data = f.read()
print(len(data))
# 在大文件中,开头| 1/3 | 2/3 | 末尾 各取10个字节拼接成秒传的信息依据
# 形成秒传规则
tagData = b''
with open('001.png', 'rb') as f:
# 通过其他途径(sys模块)来获取文件总大小
data = f.read()
length = len(data)
# 开头
f.seek(0, 0)
d1 = f.read(10)
# 1/3
f.seek(length // 3, 0)
d2 = f.read(10)
# 2/3
f.seek(length // 3 * 2, 0)
d3 = f.read(10)
# 末尾
f.seek(-10, 2)
d4 = f.read(10)
tagData = d1 + d2 + d3 + d4
# 秒传依据
print(tagData)
newData = b""
with open('001.png', 'rb') as f:
data = f.read()
length = len(data)
f.seek(0, 0)
newData += f.read(10)
f.seek(length // 3, 0)
newData += f.read(10)
f.seek(length // 3 * 2, 0)
newData += f.read(10)
f.seek(-10, 2)
newData += f.read(10)
if newData == tagData:
print('秒传成功')
else:
print('慢慢传去吧')
7. with:将文件的释放交给with管理
7.1 使用方法
with open('1.txt', 'r', encoding='utf-8') as r,\
open('source.txt', 'w', encoding='utf-8') as w:
for line in r:
w.write(line)
w.flush()
# w.close() 系统自动完成
# r.close()
7.2 案例
#完成文本文件的赋值
# 边读边写赋值
with open('source.txt', 'r', encoding='utf-8') as f1:
with open('target.txt', 'a+', encoding='utf-8') as f2:
for line in f1:
f2.write(line)
#完成非文本文件的赋值
# 非文本文件,使用二进制读写,不设置encoding
with open('333.mp4', 'rb') as f1:
with open('666.mp4', 'wb+') as f2:
for line in f1:
f2.write(line)