Python学习-对文件的操作
记录下python中文件的操作,文件操作主要三步:打开文件、操作文件句柄、关闭文件句柄。以下为打开一个文件的实例,使用open方法打开,f为文件句柄。
f=open(r'长沙4S店联系方式.txt',encoding='utf-8',mode='r')
其中打开文件使用open函数,其为内置函数,底层调用的是操作系统的接口。第一个参数为路径,路径名前加一个r,可以规避路径里转义的问题。
encoding可以默认不写,编码默认是操作系统的默认编码,windows默认是gbk,linux和macOS默认是utf-8。
mode为打开的方式,有读(r)、写(w)、追加(a)、读写(rw)。
文件读
文件读可以整个文件读、按照字符读取、按行读取、多行读取、for循环读取,操作文件内容如下。
messi
ronald
herry
(1)全部读取
f1=open(r'文件的读.txt',encoding='utf-8')
# 1 read全部读出来 整个文件读取
content=f1.read()
print(content,type(content))
f1.close()
(2)按照字符读取
# 2 read(n) 按照字符读取
content=f1.read(5) # 'messi',读取了5个字符
print(content)
f1.close()
(3)按行读取,多行读取
# 3 按照行来读
print(f1.readline()) # messi
print(f1.readline()) # ronald
# 4 readlines() 整个文件读取,返回列表
print(f1.readlines()) #['messi\n', 'ronald\n', 'herry']
(4)for循环读取
当文件非常大时,这种读取方式显然是更好的,每次读取只会读取一行的数据到内存,打印完后把内存中这行删除掉。
# 5 for循环读取
for line in f1:
print(line)
f1.close()
# 结果
messi
ronald
herry
读取一个文件时mode可以选r、rb、r+、r+b,一般使用r和rb,具体如下表。
mode | 说明 |
---|---|
r | 只读方式打开文件,操作的一般是文本文件,指针默认会放在文件开头 |
rb | 二级制格式打开一个文件用于只读,操作的一般是非文本的文件,如音频、视频、图片,指针默认会放在文件开头 |
r+ | 打开文件用于读写,指针默认在文件开头 |
r+b | 以二进制格式打开一个文件用于读写,指针在文件开头 |
如使用rb打开图片内容如下无实际意义,可再写入到文件用于复制图片。
f2=open('美女.jpg',mode='rb')
content=f2.read()
print(content)
f2.close()
# 读取后以字节形式展示
\xfe/z\xa8\xdb\xa9:\x94\xc5\xb1\xdb\xf5\xa65\xb7?\x85^\x08E1\xd3\x00\xff\x00JN\xe0U\x10\xe2\x9a\xf1e\xea\xc3.\x07\xf3\xa6\xca\xb8\xff\x00\xf5\xd4u\x0b\x15\xde=\xd4\xdf\'&\xa6\x1cSJ\xed>\xa6\xa8\x08[\xe4\x1f\xca\x800)\xce\xfcc\xd6\x9b\x8c\x8a\x05`\xf2\xc9\x1e\xbcPF3N^\x7f\x955\x8e\xda
文件写
文件的写操作,直接使用write方法到文件。
f=open('文件的写.txt',encoding='utf-8',mode='w')
f.write('我是最帅的')
f.close()
写一个文件时mode可以选可以选择w、wb、w+、w+b,具体如下表。
mode | 说明 |
---|---|
w | 打开一个文件只用于写入,如果文件不存在就创建新文件写入内容,如果文件存在就清空原来的内容,写入新的内容 |
wb | 二级制格式打开一个文件用于只写入,操作的一般是非文本的文件,如音频、视频、图片,如果文件不存在就创建新文件写入内容,如果文件存在就清空原来的内容,写入新的内容 |
w+ | 打开文件用于读写,如果文件不存在就创建新文件写入内容,如果文件存在就清空原来的内容,写入新的内容 |
w+b | 以二进制格式打开一个文件用于读写,如果文件不存在就创建新文件写入内容,如果文件存在就清空原来的内容,写入新的内容 |
下例为使用rb模式打开图片内容再写入到文件用于复制。
# 先读取内容
f1=open('美女.jpg',mode='rb')
content=f1.read()
f1.close()
# 写入读取的内容实现复制
f2=open('美女copy.jpg',mode='wb')
f2.write(content)
f2.close()
文件追加
文件的追加,也是用write方法,模式更换为a即可,其会在文件末尾追加内容,不会像写模式的直接覆盖。
# 文件的追加,没有文件就创建一个文件追加
f=open('文件的追加.txt',encoding='utf-8',mode='a')
f.write('\n我最帅')
f.close()
# 有文件,就在原来的基础上,追加内容
f=open('文件的追加.txt',encoding='utf-8',mode='a')
f.write('\n我也最坏')
f.close()
# 执行完后文件内容
我最帅
我也最坏
追加一个文件时mode可以选可以选择a、ab、a+、a+b,具体如下表。
mode | 说明 |
---|---|
a | 打开一个文件只用于追加,如果文件不存在就创建新文件写入内容,如果文件存在,指针放到文件结尾写入新的内容到已有内容之后 |
ab | 二级制格式打开一个文件用于追加,如果文件不存在就创建新文件写入内容,如果文件存在,指针放到文件结尾写入新的内容到已有内容之后 |
a+ | 打开文件用于读写,如果文件不存在就创建新文件用于读和追加,如果文件存在,指针放到文件结尾。 |
a+b | 以二进制格式打开一个文件用于追加,如果文件不存在就创建新文件用于读和追加,如果文件存在,指针放到文件结尾。 |
打开文件的其他操作
使用操作文件内容如下。
messi
(1)先读后写
使用r+模式,刚开始指针默认在文件开头,执行read方法后指针移到文件末尾,再次写入内容会追加到文件末尾
# 先读后写
f1=open(r'文件的读.txt',encoding='utf-8',mode='r+')
content=f1.read()
print(content) # messi
print('目标光标位置:',f1.tell()) # 目标光标位置: 5,utf-8的编码格式,中文一个字符3个字节,英文一个字符1个字节
f1.write('\n先读后写的内容')
f1.close()
执行完后,文件内容如下,中文内容写到文件末尾。
messi
先读后写的内容
(2)先写后读
使用操作文件内容如下。
我为我儿子学编程哈哈
使用r+模式,刚开始指针默认在文件开头,执行write方法后指针移到写入内容的末尾。
# 先写后读
f1=open('文件的读.txt',encoding='utf-8',mode='r+')
f1.write('先读后写的内容')
content=f1.read()
print(content) # 程哈哈
f1.close()
执行完后,文件内容如下,光标从文件开头写完内容,最后光标会移动到写入部分文件的末尾,原文件内容还有部分未被覆盖,再执行read方法读取的就是'程哈哈'。
先读后写的内容程哈哈
以上两种情况,考虑指针移动的位置,就好理解。
tell seek flush
操作文件内容如下。
abc123中
(1)tell() :获取光标字节位置
代码如下,光标位置刚开始在文件开头,tell执行后为0,读取内容后光标移动到文件末尾,再次tell执行后为9,utf-8的编码格式下,'abc123'占用6个字节,'中'占用3个字节。
f1=open('文件操作的其他功能.txt',encoding='utf-8',mode='r')
print(f1.tell()) # 0
print(f1.read()) # abc123中
print(f1.tell()) # 9
(2)seek(): 调整光标的字节位置
代码如下,光标移动6位后,走过了'abc123',再次读取后内容为'中'。
f1=open('文件操作的其他功能.txt',encoding='utf-8',mode='r')
f1.seek(6)
print(f1.read()) # 中
方法tell和seek可以用在文件断点续传。
(3)flush() :强制刷新,用来把文件从内存缓冲区中强制刷新到硬盘中,同时清空缓冲区。一般情况下,文件句柄关闭后会自动刷新到硬盘,但有时需要在关闭前刷新到硬盘,这时就可以使用 flush() 方法。
f1=open('文件的写.txt',encoding='utf-8',mode='w')
f1.write('hello')
f1.write('python')
f1.flush()
print(f1.tell()) # hellopython
f1.close()
with open打开文件
有点类似SQL里的with as,代码如下,这种不需要手动关闭文件句柄。
# 不用手动关闭文件句柄
with open('文件的读.txt',encoding='utf-8') as f1:
print(f1.read())
# 一个with,可以操作多个open
with open('文件的读.txt',encoding='utf-8',mode='r') as f1,open('文件的写.txt',encoding='utf-8',mode='w') as f2:
print(f1.read())
f2.write('打开文件的另外一种方式')
文件的修改
操作文件内容如下。
clyang是最帅的
当然,clyang也是最坏的
你问clyang是谁,那就是我了
python中没有文件修改的方法,需要使用取巧的方式实现,步骤如下。
- 以读的模式打开源文件
- 以写的模式创建一个新文件
- 将源文件的内容读取出来并修改成新内容,写入新文件
- 将源文件删除
- 将新文件重命名为原文件
# low版本的修改,没有考虑内存溢出
import os
with open('文件的修改.txt', encoding='utf-8', mode='r') as f1, \
open('文件的修改.txt_bak', encoding='utf-8', mode='w') as f2:
# 读取文件内容
content = f1.read()
# 修改
new_content=content.replace('clyang','超哥')
# 写入新文件
f2.write(new_content)
# 删除旧文件
os.remove('文件的修改.txt')
# 重命名新文件
os.rename('文件的修改.txt_bak','文件的修改.txt')
# 进阶版,考虑内存溢出
import os
with open('文件的修改.txt', encoding='utf-8', mode='r') as f1, \
open('文件的修改.txt_bak', encoding='utf-8', mode='w') as f2:
for line in f1:
# 读一行,修改一行
new_line=line.replace('超哥','clyang')
# 修改一行,写一行
f2.write(new_line)
# 删除旧文件
os.remove('文件的修改.txt')
# 重命名新文件
os.rename('文件的修改.txt_bak','文件的修改.txt')
执行后文件内容中'clyang'都被替换。
超哥是最帅的
当然,超哥也是最坏的
你问超哥是谁,那就是我了
文件操作练习
使用文件操作,结合前面学习的知识点,练习一下。
练习1 追加模式修改内容并读取
在如下内容上,以a+模式添加"卧梅又闻花",然后从最开始将原内容读取出来。
葫芦娃,葫芦娃,
一根藤上七个瓜,
风吹雨打,都不怕,
啦啦啦啦。
上代码,追加内容后,需要使用seek调整光标的字节位置到开头后读取内容。
seek(0):光标移动到最前面;seek(0,2):光标移动到最后面
with open('葫芦娃',encoding='utf-8',mode='a+') as f1:
f1.write('\n卧梅又闻花')
# 光标移动到最前面
f1.seek(0)
# 光标移动到最后面,2就是文件尾
# f1.seek(0,2)
content=f1.read()
# 退回5个字符,读取原文件内容
print(content[:-5])
练习2 读取商品文件生成列表
文件price.txt中的内容,每一行内容分别为商品名 价钱 个数,中间空格隔开。需要通过代码,构建成列表数据类型,元素为字典类型: [{'name':'apple','price':10,'amount':3},{'name':'benz','price':200000,'amount':1},...],并计算总价。
apple 10 3
benz 200000 1
mac 8888 2
acer 4500 3
chicken 10 5
上代码,除了读取文件部分为新增知识,其他都是以前的知识点,下面是常规的方法,首先想到就是这种思路。
li=[]
with open('price.txt',encoding='utf-8',mode='r') as f1:
for line in f1:
data=line.split(' ')
name=data[0]
price=int(data[1])
amount=int(data[2].strip())
# 添加到字典
# 以下两张方法都可以
# dic={}
# dic['name']=name
# dic['price']=price
# dic['amount']=amount
dic={'name':name,'price':price,'amount':amount}
# 添加到列表
li.append(dic)
print(li)
# 统计总价
sum=0
for item in li:
sum+=item.get('price')*item.get('amount')
print('商品总价为{}'.format(sum))
生成字典并append到列表前,字典的生成有诀窍,如果文件内容新增一列或多列,按照上面代码写法,需要把字典后面的字段进行补充,会增加代码行数。按照下面的写法将更加灵活,文件增加列数,只需要增加在li_name列表中添加key即可,其他代码均不需要修改。
li=[]
li_name=['name','price','amount'] # 如果原文件增加一列,只需要在这里添加key就可以,其他不用修改
with open('price.txt',encoding='utf-8',mode='r') as f1:
for line in f1:
# key和value一一对应的数据都准备好了
item_list=line.strip().split()
dic = {}
# 循环,生成字典
for index in range(len(li_name)):
dic[li_name[index]]=item_list[index]
li.append(dic)
print(li)
修改后执行效果。
[{'name': 'apple', 'price': '10', 'amount': '3'}, {'name': 'benz', 'price': '200000', 'amount': '1'}, {'name': 'mac', 'price': '8888', 'amount': '2'}, {'name': 'acer', 'price': '4500', 'amount': '3'}, {'name': 'chicken', 'price': '10', 'amount': '5'}]
PS:以上,理解不一定正确,学习就是一个不断认识和纠错的过程,如果有误还请批评指正。
参考博文:
(1)https://www.cnblogs.com/on2road/p/12044503.html r+和w+