python文件操作
文件以什么编码存储,就以什么编码打开
参数:
1 文件路劲
2 编码方式
3 执行动作(打开方式):只读,只写,追加,读写,写读
例子
现有一个文档,制服护士空姐萝莉联系方式.txt,怎么用python打开?
f = open('D:\制服护士空姐萝莉联系方式.txt', encoding='gbk', mode='r')
content = f.read()
print(content)
f.close()
执行结果
没睡醒?赶紧去写代码吧。
上面例子讲解
f:变量 文件句柄
open 调用windows的系统功能,执行打开文件的动作
windows 默认编码方式:gbk,linux默认编码方式utf-8
r: 执行读的操作
f.close() 关闭文件
流程:打开一个文件,产生一个文件句柄,对文件句柄进行操作,关闭文件
读:
r,只读,以str方式读取
rb,只读,以bytes类型读取(非文字类的文件时,用rb,比如图片,音频文件等)
下面一个例子
f = open('D:\qycache\test.txt',encoding='utf-8')
content = f.read()
print(content)
f.close()
默认mode不写,表示只读模式
编码不一致时,报错
UnicodeDecodeError: 'gbk' codec can't decode byte 0xaa in position 14: illegal multibyte sequence
文件以什么编码存储的,就用什么编码打开
文件路径。
绝对路径:从根目录开始,一级一级查找直到找到文件
相对路径:在同一个文件夹下,直接写文件名即可
相对路径举例
f = open('username.txt',encoding='utf-8')
content = f.read()
print(content)
f.close()
务必保证python代码和txt文件在同一文件夹下
某些windows系统,读取文件的时候报错
[Error 22] Invalid argument: '\u202adD:\\xx.txt'
解决方法
第一种前面加个r: r'C:\log.txt'
第二种前面多加个斜杠,表示转义: C:\\log.txt
python r模式有5种模式读取
1:全部读出来f.read()
f = open('tianqi.txt',encoding='utf-8')
content = f.read()
print(content)
f.close()
执行输出
03月27日(今天)
晴转多云
11~27℃
西南风 1级
重度污染
2: 一行行的读f.readline()
f = open('天气.txt',encoding='utf-8')
print(f.readline())
print(f.readline())
print(f.readline())
f.close()
3: 将原文件的每一行作为一个列表的元素f.readlines()
f = open('天气.txt',encoding='utf-8')
print(f.readlines())
f.close()
执行输出
['03月27日(今天)\n', '晴转多云\n', '11~27℃\n', '西南风 1级\n', '重度污染']
4: 读取一部分read(n)
在r模式下,read(n)按照字符去读取
f = open('天气.txt',encoding='utf-8')
print(f.read(3))
f.close()
执行输出
03月
5:for循环读取(也是做好的一种方式)
f = open('天气.txt',encoding='utf-8')
for i in f:
print(i.strip())
f.close()
执行输出
03月27日(今天)
晴转多云
11~27℃
西南风 1级
重度污染
在for循环中,每次读取一行,结束之后,内存就释放了。所以在整个for循环个过程中,始终只占用了一行内容的内存。
推荐使用第5种方式
写操作(w)
w 文件不存在时,创建一个文件写入内容
有文件时,将原文件内容清空,再写入内容
f = open('log.txt',encoding='utf-8',mode='w')
f.write('人生苦短,我想学Python')
f.close()
wb以bytes写入,写入的内容,必须要转换为bytes类型才可以
a追加
没有文件时,创建一个文件追加内容
有文件时,直接追加内容
f = open('log2.txt',encoding='utf-8',mode='a')
f.write('666')
f.close()
r+读写,先读,后追加
错误的写法
f = open('log.txt',encoding='utf-8',mode='r+')
f.write('BBB')
content = f.read()
print(content)
f.close()
执行输出,内容为空
为什么呢?
因为光标,默认是从0开始。只要进行一个动作,光标就会移动,包括读取。
上面的代码写入时,光标移动到最后了。所以执行f.read()时,读取不到后面的内容了。
r+ 一定要先读后写,否则会错乱或者读取不到内容
w+ 先写后读
f = open('log.txt',encoding='utf-8',mode='w+')
f.write('AAA')
content = f.read()
print(content)
f.close()
执行输出,内容是空的
写完之后,光标移动到最后了,所以读取的时候,读取不到内容了
正确的写法
f = open('log.txt',encoding='utf-8',mode='w+')
f.write('AAA')
print(f.tell()) #按直接去读光标位置
f.seek(0) #调整光标位置
content = f.read()
print(content)
f.close()
执行输出
3
AAA
下面一个例子
f = open('log.txt',encoding='utf-8',mode='w+')
f.write('中国')
print(f.tell()) #按直接去读光标位置
f.seek(2) #调整光标位置
content = f.read()
print(content)
f.close()
执行输出:
6
......
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xad in position 0: invalid start byte
因为一个中文占用3字节
ftp的断点续传,需要用到光标,一定会用到tell和seek
a+追加读,就不一一举例了
用的最多的还是r和r+模式,r的5种模式中,重点掌握第5种,for的方法
其它操作方法
其他操作方法:
truncate #截取文件
writable() #是否可写
readable() #是否可读
truncate是截取文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果
f = open('log.txt',encoding='utf-8',mode='r+')
# 截取10个字节
f.truncate(3)
content = f.read()
print(content)
f.close()
执行输出
中
判断是否可写
f = open('log.txt',encoding='utf-8',mode='r+')
print(f.writable())
f.close()
执行输出
True
回收方法为:
1、f.close() #回收操作系统级打开的文件,关闭文件句柄
2、del f #回收应用程序级的变量,在python代码级别中,删除变量
为了避免忘记回收文件句柄,需要使用with open方法,代码执行完毕之后,自动关闭文件句柄
功能1:自动关闭文件句柄
with open('log.txt',encoding='utf-8') as f:
print(f.read())
功能2:一次性操作多个文件
with open('log.txt',encoding='utf-8') as f1,\
open('log1.txt',encoding='utf-8',mode='r+') as f2:
print(f1.read())
print(f2.read())
有些情况下,必须先关闭,才能执行某某动作的情况下,不能用with,这种情况比较少见。
推荐使用with open
所有的软件,不是直接在原文件修改的。
它是进行了5步操作
1.将原文件读取到内存。
2.在内存中进行修改,形成新的内容。
3.将新的字符串写入新文件。
4.将原文件删除。
5.将新文件重命名成原文件。
将log文件内容中含有张三的,替换为李四
import os
#第1步
with open('log',encoding='utf-8') as f1,\
open('log.bak',encoding='utf-8',mode='w') as f2:
content = f1.read()
#第2步
new_content = content.replace('张三','李四')
#第3步
f2.write(new_content)
#第4步
os.remove('log')
#第5步
os.rename('log.bak','log')
这种方法不好,如果文件比较大,内存直接爆掉,因为f1.read()是将文件所有内容读取到内容中存放
推荐做法
import os
#第1步
with open('log',encoding='utf-8') as f1,\
open('log.bak',encoding='utf-8',mode='w') as f2:
for i in f1:
#第3步
new_i = i.replace('张三', '李四')
#第4步
f2.write(new_i)
#第4步
os.remove('log')
#第5步
os.rename('log.bak','log')
这种方式,每次只占用一行。
所有软件,都是执行这5步的
习题练习:
#!/usr/bin/env python
# coding: utf-8
__author__ = 'www.py3study.com'
# 1. 文件a.txt内容:每一行内容分别为商品名字,价钱,个数。
# apple 10 3
# tesla 100000 1
# mac 3000 2
# lenovo 30000 3
# chicken 10 3
# 通过代码,将其构建成这种数据类型:[{'name':'apple','price':10,'amount':3},{'name':'tesla','price':1000000,'amount':1}......] 并计算出总价钱。
#方法一
dic = {}
num = 0
sum1 = 0
with open('zuoye1.txt', encoding='utf-8', mode='r') as f1:
for i in f1:
ss = i.split()
if ss[0] not in dic:
num += 1
dic['key' + str(num)] = {'name': ss[0], 'price': int(ss[1]), 'amount': int(ss[2])}
else:
dic['key' + str(num)] = {'name': ss[0], 'price': int(ss[1]), 'amount': int(ss[2])}
print(list(dic.values()))
for i in dic.values():
sum1 += i['amount'] * i['price']
print(sum1)
# 方法二
l1 = []
name_list = ['name', 'price', 'amount', 'year']
with open('zuoye1.txt', encoding='utf-8', mode='r') as f1:
for i in f1:
l2 = i.strip().split()
#print(l2)
dic = {}
for j in range(len(l2)):
dic[name_list[j]] = l2[j] # dic[name] = apple dic[price] = 10 .....
l1.append(dic)
sum1 = 0
sum2 = 0
for i in l1:
sum1 = int(i['amount']) * int(i['price'])
sum2 += sum1
print(sum2)
# 3. 文件a1.txt内容:每一行内容分别为商品名字,价钱,个数。
# 文件内容:
# name:apple price:10 amount:3 year:2012
# name:tesla price:100000 amount:1 year:2013
#
# 通过代码,将其构建成这种数据类型:
# [{'name':'apple','price':10,'amount':3},
# {'name':'tesla','price':1000000,'amount':1}......]
# 并计算出总价钱。
# 思路 {key1 : {'name':'apple','price':10,'amount':3} ....}
dic = {}
num2 = 0
sum2 = 0
with open("zuoye3.txt", encoding='utf-8', mode='r') as f1:
for i in f1:
ss = i.strip().replace(' ', ':').split(':')
#print(ss)
num2 += 1
if ss[0] not in dic:
dic['key' + str(num2)] = {ss[0]: ss[1], ss[2]: ss[3], ss[4]: ss[5], ss[6]: ss[7]}
else:
dic['key' + str(num2)] = {ss[0]: ss[1], ss[2]: ss[3], ss[4]: ss[5], ss[6]: ss[7]}
print(list(dic.values()))
for i in dic.values():
#print(i)
sum2 += int(i['amount']) * int(i['price'])
print("总价钱为:{}".format(sum2))
# 4,文件a2.txt内容:每一行内容分别为商品名字,价钱,个数。
# 文件内容:
# 序号 部门 人数 平均年龄 备注
# 1 python 30 26 单身狗
# 2 Linux 26 30 没对象
# 3 运营部 20 24 女生多
# 通过代码,将其构建成这种数据类型:
# [{'序号':'1','部门':Python,'人数':30,'平均年龄':26,'备注':'单身狗'},
# ......]
# 并计算出总价钱。
# 思路 {'序号':'1','部门':Python,'人数':30,'平均年龄':26,'备注':'单身狗'}
dic = {}
list1 = []
num = 0
sum4 = 0
with open("zuoye4.txt", encoding='utf-8', mode='r') as f1:
for i in f1.readlines(1):
ss = i.strip().split()
for y in ss:
list1.append(y.strip())
for x in f1:
x = x.split()
num += 1
if x[0] not in list1[0]:
dic['key' + str(num)] = {list1[0]: x[0], list1[1]: x[1], list1[2]: x[2], list1[3]: x[3], list1[4]: x[4]}
new_dic = list(dic.values())
print(new_dic)
for y in new_dic:
sum4 += int(y['人数'])
# 总人数
print('总人数:{}'.format(sum4))