day3-文件操作
一 概述
Python对文件的操作流程
- 打开文件,得到文件句柄并赋值给一个变量
- 通过句柄对文件进行操作
- 关闭文件
现有文件如下
Somehow, it seems the love I knew was always the most destructive kind 不知为何,我经历的爱情总是最具毁灭性的的那种 Yesterday when I was young 昨日当我年少轻狂 The taste of life was sweet 生命的滋味是甜的 As rain upon my tongue 就如舌尖上的雨露 I teased at life as if it were a foolish game 我戏弄生命 视其为愚蠢的游戏 The way the evening breeze 就如夜晚的微风 May tease the candle flame 逗弄蜡烛的火苗 The thousand dreams I dreamed 我曾千万次梦见 The splendid things I planned 那些我计划的绚丽蓝图 I always built to last on weak and shifting sand 但我总是将之建筑在易逝的流沙上 I lived by night and shunned the naked light of day 我夜夜笙歌 逃避白昼赤裸的阳光 And only now I see how the time ran away 事到如今我才看清岁月是如何匆匆流逝 Yesterday when I was young 昨日当我年少轻狂 So many lovely songs were waiting to be sung 有那么多甜美的曲儿等我歌唱 So many wild pleasures lay in store for me 有那么多肆意的快乐等我享受 And so much pain my eyes refused to see 还有那么多痛苦 我的双眼却视而不见 I ran so fast that time and youth at last ran out 我飞快地奔走 最终时光与青春消逝殆尽 I never stopped to think what life was all about 我从未停下脚步去思考生命的意义 And every conversation that I can now recall 如今回想起的所有对话 Concerned itself with me and nothing else at all 除了和我相关的 什么都记不得了 The game of love I played with arrogance and pride 我用自负和傲慢玩着爱情的游戏 And every flame I lit too quickly, quickly died 所有我点燃的火焰都熄灭得太快 The friends I made all somehow seemed to slip away 所有我交的朋友似乎都不知不觉地离开了 And only now I'm left alone to end the play, yeah 只剩我一个人在台上来结束这场闹剧 Oh, yesterday when I was young 噢 昨日当我年少轻狂 So many, many songs were waiting to be sung 有那么那么多甜美的曲儿等我歌唱 So many wild pleasures lay in store for me 有那么多肆意的快乐等我享受 And so much pain my eyes refused to see 还有那么多痛苦 我的双眼却视而不见 There are so many songs in me that won't be sung 我有太多歌曲永远不会被唱起 I feel the bitter taste of tears upon my tongue 我尝到了舌尖泪水的苦涩滋味 The time has come for me to pay for yesterday 终于到了付出代价的时间 为了昨日 When I was young 当我年少轻狂
二 入门
1.语法
open(文件路径,模式,字符编码)
f = open("music.txt",'r',encoding="utf-8") #获取文件句柄 date = f.read() #读取数据 print(date) #打印读取的文件 f.close() #关闭文件
注:f 又叫文件句柄,它包含文件的文件名,字符集,文件大小,文件在硬盘上的起始位
2. 两次读取文件内容
f = open("music.txt",'r',encoding="utf-8") date = f.read() date2 = f.read() #读取数据为空 print(date) print("-------data2-----",date2) f.close() #输出结果 Somehow, it seems the love I knew was always the most destructive kind 不知为何,我经历的爱情总是最具毁灭性的的那种 Yesterday when I was young 昨日当我年少轻狂 The taste of life was sweet 生命的滋味是甜的 As rain upon my tongue 就如舌尖上的雨露 -------data2-----
第二次读取数据为空,因为在文件中,维护一个类似文件指针的东西,这个文件指针类似于我们平时操作文件时的光标,第一次读文件时,文件指针已经只想文件最后的位置,所以第二次再去读取的时候,是从最后一个位置开始读取的,所以读取为空。想要重新读取文件内容,需要把光标移动到开始位置即可。
3. 打开文件模式
- r 只能读
- r+ r+可读可写,不会创建不存在的文件。如果直接写文件,则从顶部开始写,覆盖之前此位置的内容,如果先读后写,则会在文件最后追加内容
- w 只能写 覆盖整个文件 不存在则创建
- w+ 可读可写 如果文件存在 则覆盖整个文件不存在则创建
- a 只能写 从文件底部添加内容 不存在则创建
- a+ 可读可写 从文件顶部读取内容 从文件底部添加内容 不存在则创建
"U" 表示在读取文件时,可以把\r \n \r\n自动转化为\n (与r 或r+ 模式同时使用)
- rU
- r+U
"b"表示处理二进制文件
- rb
- wb
- ab
需要详细了解文件打开模式:这里
4. 高效读取文件行
首先介绍一下readline和readlines
- readline()
读取一行文件
f = open("music.txt",'r',encoding="utf-8") print(f.readline().strip()) print(f.readline()) f.close() #输出 Somehow, it seems the love I knew was always the most destructive kind 不知为何,我经历的爱情总是最具毁灭性的的那种
- readlines()
把文件中的每一行作为一个元素形成一个列表,整体读取
f = open("music.txt",'r',encoding="utf-8") print(f.readlines()) f.close() #输出 ['Somehow, it seems the love I knew was always the most destructive kind\n', '不知为何,我经历的爱情总是最具毁灭性的的那种\n', 'Yesterday when I was young\n', '昨日当我年少轻狂\n', 'The taste of life was sweet\n', '生命的滋味是甜的\n', 'As rain upon my tongue\n', '就如舌尖上的雨露']
正常循环读取文件中的每一行,如下
f = open("music.txt",'r',encoding='utf-8') for index,line in enumerate(f.readlines()): if index == 2: print("-----new-----") continue print(line.strip()) f.close() #输出 Somehow, it seems the love I knew was always the most destructive kind 不知为何,我经历的爱情总是最具毁灭性的的那种 -----new----- 昨日当我年少轻狂 The taste of life was sweet 生命的滋味是甜的 As rain upon my tongue 就如舌尖上的雨露
enumerate()说明
- enumerate()是python的内置函数
- enumerate在字典上是枚举、列举的意思
- 对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值
- enumerate多用于在for循环中得到计数
这种方法已经达到我们的目的了,可以顺利的读取每一行,但是,当我们遇到2G,20G 甚至200G的文件时,这样读取会导致内存不够用,会使程序变得很慢,因为你的内存只有几个G,你把几十个G的数据放到内存,内存肯定受不了的,所以这种方法只适合小文件,不适合大文件。我们可以采用下面这种方法:
with open("music.txt",'r',encoding='utf-8') as f: count = 0 for line in f: if count == 2: print("-----data----") count +=1 continue print(line.strip()) count += 1 #输出 Somehow, it seems the love I knew was always the most destructive kind 不知为何,我经历的爱情总是最具毁灭性的的那种 -----data---- 昨日当我年少轻狂 The taste of life was sweet 生命的滋味是甜的 As rain upon my tongue 就如舌尖上的雨露
以上这种写法的好处在于,读取文件时,是一行一行的读取,而且,读取一行删除一行,内存中只保留一行。原因:f文件变成迭代器,它已经不再是一个列表的形式了,不能通过下标值来获取,需要一个计数器来计数。
三 基本操作
1. read()
从文件读取指定的字节数,如果未给定或为负数则读取所有
f = open('music.txt','r',encoding='utf-8') print(f.read()) #读取全部 f.close()
f = open('music.txt','r',encoding='utf-8') print(f.read(10)) #读取10个字节 f.close()
2. tell()
返回文件的当前位置,即文件指针当前位置
f = open('music.txt','r',encoding='utf-8') print(f.read(10)) print(f.tell()) #获取文件指针当前位置 f.close() #输出 Somehow, i 10
3. seek()
移动文件读取指针到指定位置
f = open('music.txt','r',encoding='utf-8') print(f.read(10)) print(f.tell()) #获取当前指针位置 f.seek(4) #设置指针位置 print(f.tell())# 获取设置后的指针位置 f.close() #输出 Somehow, i 10 4
4. encoding
返回文件的编码
f = open('music.txt','r',encoding='utf-8') print(f.encoding) f.close() #输出 utf-8
5. fileno
返回一个整形的文件描述符(file descriptor FD 整型),可用于底层操作系统的I/O操作
f = open('music.txt','r',encoding='utf-8') print(f.fileno()) f.close() #输出 3
6. name
返回文件名
f = open('music.txt','r',encoding='utf-8') print(f.name) f.close() #输出 music.txt
7. isatty()
检测文件是否连接到一个终端设备,如果是返回True,,否则返回False
f = open('music.txt','r',encoding='utf-8') print(f.isatty()) f.close() #输出 False
8. seekable()
判断光标是否可以移动。不是所有的文件都可以移动光标,比如tty文件;可以移动的,返回True,否则返回False
f = open('music.txt','r',encoding='utf-8') print(f.seekable()) f.close() #输出 True
9. readable()
判断文件是否可读
f = open('music.txt','r',encoding='utf-8') print(f.readable()) f.close() f = open('music.txt','w',encoding='utf-8') print(f.readable()) f.close() #输出 True False
10. writeable()
判断文件是否可写
f = open('music.txt','r',encoding='utf-8') print(f.writable()) f.close() f = open('music.txt','w',encoding='utf-8') print(f.writable()) f.close() #输出 False True
11. closed
判断文件是否关闭
f = open('music.txt','r',encoding='utf-8') f.read() print(f.closed) f.close() print(f.closed) #输出 False True
12. truncate(n)
从文件的首行首字符开始截断,截断文件为n个字符;无n表示从当前位置截断;截断之后n后面的所有字符将被删除。其中win下的换行代表2个字符大小
#循环读取文件内容 f = open('music.txt','r+',encoding='utf-8') print(f.readline()) f.truncate() #截断,但无n,则不删除后面的字符,只做截断 print(f.readlines()) f.close() #输出结果 Somehow, it seems the love I knew was always the most destructive kind ['哇哦呵呵,我经历的爱情总是最具毁灭性的的那种\n', 'Yesterday when I was young\n', '昨日当我年少轻狂\n', 'The taste of life was sweet\n', '生命的滋味是甜的\n', 'As rain upon my tongue\n', '就如舌尖上的雨露']
f = open("music.txt",'r+',encoding='utf-8') f.truncate(10) print(f.read()) f.close() #输出 Somehow, i
13. write()
写入文件内容
f = open("music.txt",'w',encoding='utf-8') f.write('babazyzy') #写入文件内容,'w' 会覆盖文件所有内容 f.close()
14. flush()
用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件(硬盘),同时清空缓冲区,不需要被动的等带输出缓冲区写入文件(硬盘)。
一般情况下,文件关闭后会自动刷新缓冲区,但有时需要在关闭之前刷新它,这个时候就可以使用flush()方法。
四 with语句
为了避免打开文件后忘记关闭,可通过管理上下文,即:
with open('log','r') as f: ....
如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。
在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:
with open('log1') as obj1, open('log2') as obj2: pass
上面打开多个文件会导致一行代码过长,python官方建议,一行代码不超过80个字符,所以打开多个文件建议以下写法:
with open('log1') as obj1, \ open('log2') as obj2: pass
五 文件修改
修改文件,可以先读文件,一边读操作,再一边写(写需要打开一个新的文件,成功后,把老文件删掉,把新文件重命名为老文件)
with open("music.txt",'r',encoding='utf-8') as f, \ open("music_new.txt",'w',encoding='utf-8') as f_new: for line in f: if "不知为何" in line: line = line.replace('不知为何','哇哦呵呵') f_new.write(line)