今日内容:
文件打开模式
读写文件的方法
文件处理高级
控制文件内指针的移动
改文件的两种方式
**四 操作文件的方法**
**4.1 重点**
# 读操作
f.read() # 读取所有内容,执行完该操作后,文件指针会移动到文件末尾
f.readline() # 读取一行内容,光标移动到第二行首部
f.readlines() # 读取每一行内容,存放于列表中
**# 强调:**
# f.read()与f.readlines()都是将内容一次性读入内容,如果内容过大会导致内存溢出,
若还想将内容全读入内存,则必须分多次读入,有两种实现方式:
**# 方式一**
with open('a.txt',mode='rt',encoding='utf-8') as f:
for line in f:
print(line) # 同一时刻只读入一行内容到内存中
**# 方式二**
with open('1.mp4',mode='rb') as f:
while True:
data=f.read(1024) # 同一时刻只读入1024个Bytes到内存中
if len(data) == 0:
break
print(data)
**# 写操作**
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.readable() # 文件是否可读
f.writable() # 文件是否可读
f.closed # 文件是否关闭
f.encoding # 如果文件打开模式为b,则没有该属性
f.flush() # 立刻将文件内容从内存刷到硬盘
f.name
**文件打开模式**
创建一个a.txt文件
with open(r'a.txt',mode='wt',encoding='utf-8') as f:
f.write("你好")
with open(r'a.txt',mode='ab') as f:
f.write("哈哈哈".encode('utf-8'))
with open(r'a.txt',mode='rb') as f:
data = f.read()
print(data.decode('utf-8'))
with open(r'1.mp4',mode='rb') as f:
# data = f.read()
# print(data)
for line in f:
print(line)
with open('1.mp4',mode='rb') as f1,open(r'D:\111111111111.mp4',mode='wb') as f2:
# data = f1.read()
# f2.write(data)
for line in f1:
f2.write(line)
**可读可写模式**
with open('a.txt',mode='r+t',encoding='utf-8') as f:
# f.write('次卧')
f.write('h')
**修改文件的两种方式**
**# 思路一:**
# with open('b.txt',mode='rt',encoding='utf-8') as f1:
# data = f1.read()
# res = data.replace('egon','EGON')
#
# with open('b.txt',mode='wt',encoding='utf-8') as f2:
# f2.write(res)
**# 思路二**
import os
with open('b.txt',mode='rt',encoding='utf-8') as f1,open('.b.txt.swp',mode='wt',encoding='utf-8') as f2:
for line in f1:
f2.write(line.replace('EGON','egon'))
os.remove('b.txt')
os.rename('.b.txt.swp','b.txt')
**6.1 文件修改方式一**
# 实现思路:将文件内容发一次性全部读入内存,然后在内存中修改完毕后再覆盖写回原文件
# 优点: 在文件修改过程中同一份数据只有一份
# 缺点: 会过多地占用内存
with open('db.txt',mode='rt',encoding='utf-8') as f:
data=f.read()
with open('db.txt',mode='wt',encoding='utf-8') as f:
f.write(data.replace('kevin','SB'))
**6.1 文件修改方式二**
# 实现思路:以读的方式打开原文件,以写的方式打开一个临时文件,一行行读取原文件内容,修改完后写入临时文件...,删掉原文件,将临时文件重命名原文件名
# 优点: 不会占用过多的内存
# 缺点: 在文件修改过程中同一份数据存了两份
import os
with open('db.txt',mode='rt',encoding='utf-8') as read_f,\
open('.db.txt.swap',mode='wt',encoding='utf-8') as wrife_f:
for line in read_f:
wrife_f.write(line.replace('SB','kevin'))
os.remove('db.txt')
os.rename('.db.txt.swap','db.txt')
**练习**
**注册**
inp_user = input("请输入您的用名:").strip()
inp_pwd = input("请输入您的密码:").strip()
inp_money = input("请输入您的余额:").strip()
with open('db.txt', mode='at', encoding='utf-8') as f:
f.write('%s:%s:%s\n' % (inp_user, inp_pwd, inp_money))
**转账**
import os
with open('db.txt',mode='rt',encoding='utf-8') as f1,open('.db.txt.swp',mode='wt',encoding='utf-8') as f2:
for line in f1:
user,pwd,money = line.strip('\n').split(':')
if user == 'tom':
money = int(money) - 100
elif user == 'lili':
money = int(money) + 100
line = "%s:%s:%s\n" % (user, pwd, money)
f2.write(line)
os.remove('db.txt')
os.rename('.db.txt.swp','db.txt')
**文件读写的其他方法**
with open('b.txt',mode='rt',encoding='utf-8') as f:
print(f.readable())
print(f.readline())
print(f.readline())
lines = f.readlines()
print(lines[0])
with open('b.txt', mode='wt', encoding='utf-8') as f:
print(f.writable())
lines = ['你好\n', '我好\n', '大家好\n']
for line in lines:
f.write(line)
f.writelines(lines)
f.write('1111\n222\n333\n')
f.write('hello')
f.writelines('hello')
f.flush()
with open('b.txt', mode='at', encoding='utf-8') as f:
f.truncate(3)
**储备知识:**
只有t模式下的read(n)的n代表的是字符个数,除此以外都代表字节个数
with open('b.txt',mode='rt',encoding='utf-8') as f:
print(f.read(4))
with open('b.txt',mode='rb') as f:
print(f.read(3).decode('utf-8'))
f.seek(移动的字节个数,模式)
模式:
**0:**参照文件开头,只有0模式可以在t下使用,其他的都只能在b下使用
with open('b.txt',mode='rt',encoding='utf-8') as f:
f.seek(3,0)
f.seek(6,0)
print(f.tell())
**1:**参照指针当前所在的位置,只能在b下使用
with open('b.txt',mode='rb') as f:
f.seek(3,1)
f.seek(6,1)
print(f.tell())
**2:**参照指针文件末尾,通常是倒着移动,只能在b下使用
with open('b.txt',mode='rb') as f:
f.seek(-5,2)
f.seek(-8,2)
print(f.tell())
print(f.read().decode('utf-8'))
**0模式详解**
# a.txt用utf-8编码,内容如下(abc各占1个字节,中文“你好”各占3个字节)
abc你好
**# 0模式的使用**
with open('a.txt',mode='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模式的使用**
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模式详解**
# a.txt用utf-8编码,内容如下(abc各占1个字节,中文“你好”各占3个字节)
abc你好
**# 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')) # 输出结果为:好
**# 小练习**:实现动态查看最新一条日志的效果
import time
with open('access.log',mode='rb') as f:
f.seek(0,2)
while True:
line=f.readline()
if len(line) == 0:
# 没有内容
time.sleep(0.5)
else:
print(line.decode('utf-8'),end='')
**主动控制文件内指针移动**
#大前提:文件内指针的移动都是Bytes为单位的,唯一例外的是t模式下的read(n),n以字符为单位
with open('a.txt',mode='rt',encoding='utf-8') as f:
data=f.read(3) # 读取3个字符
with open('a.txt',mode='rb') as f:
data=f.read(3) # 读取3个Bytes
# 之前文件内指针的移动都是由读/写操作而被动触发的,若想读取文件某一特定位置的数据,则则需要用f.seek方法主动控制文件内指针的移动,详细用法如下:
# f.seek(指针移动的字节数,模式控制):
# 模式控制:
# 0: 默认的模式,该模式代表指针移动的字节数是以文件开头为参照的
# 1: 该模式代表指针移动的字节数是以当前所在的位置为参照的
# 2: 该模式代表指针移动的字节数是以文件末尾的位置为参照的
# 强调:其中0模式可以在t或者b模式使用,而1跟2模式只能在b模式下用
其他
**转账功能**
创建一个db.txt文件,存入一些账号密码余额
egon:123:1000
lili:456:1000
tom:789:1000
tony:999:1000
import os
with open('db.txt', mode='rt', encoding='utf-8')as f1,open('.db.txt',mode='wt',encoding='utf-8')as f2:
for line in f1:
user, pwd, money = line.strip('\n').split(':')
if user == 'tom':
new_money = int(money) - 100
new_line = '%s:%s:%s\n' %(user,pwd,new_money)
f2.write(new_line)
elif user == 'lili':
new_money = int(money) + 100
new_line = '%s:%s:%s\n' %(user,pwd,new_money)
f2.write(new_line)
else:
f2.write(line)
os.remove('db.txt')
os.rename('.db.txt','db.txt')
**操作一次输出结果 lili:456:1100 tom:789:900 实现ton转账给lili (100元)**
**优化转账功能代码(删除重复操作的代码)**
import os
with open('db.txt', mode='rt', encoding='utf-8')as f1,open('.db.txt',mode='wt',encoding='utf-8')as f2:
for line in f1:
user, pwd, money = line.strip('\n').split(':')
if user == 'tom':
money = int(money) - 100
elif user == 'lili':
money = int(money) + 100
line = '%s:%s:%s\n' %(user,pwd,money)
f2.write(line)
os.remove('db.txt')
os.rename('.db.txt','db.txt')