Python 文件操作

文件操作流程

  • 第一步,打开文件,获得文件句柄,并赋值给一个变量 ;
  • 第二步,通过句柄对文件进行相关操作;
  • 第三步,关闭文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding:utf-8 -*-
# author: cdc
# date: 2018/8/23

# 三个参数分别表示:文件 操作模式 编码
f = open('动物世界.txt',model='r',encoding='utf-8')
content = f.read()
print(content)
f.close()

#***************运行结果*****************
'''
东打一下西戳一下
动物未必需要尖牙
示爱的方法有礼貌或是我管它
要将情人一口吞下
还要显得温文尔雅
螳螂委屈的展示旧伤疤
......
'''

文件操作的不同模式

一、只读模式

1.1 不同的读取模式:

  • r:正常读取
  • rb:二进制方式读取
1
2
3
4
f = open("动物世界.txt",mode="r", encoding="utf-8") 
content = f.read()
print(content)
f.close()

encoding 表示编码集。根据文件的实际保存编码进行获取数据,对于我们而言,更多的是 utf-8。 rb 方式读取出来的数据是 bytes 类型,在 rb 模式下,不能选择 encoding 字符集。

rb 的作用: 在读取非文本文件的时候,比如 MP3、 图像、视频等信息,就需要用到 rb。 因为这种数据是没办法直接显示出来的,需要将文件转成二进制流再进行处理。

1
2
3
4
5
6
7
8
9
f = open("动物世界.txt",mode="rb" ) 
content = f.read()
print(content)
f.close()

"""
结果:
b'\xe6\xaf\x85\xe5\x93\xa5, \xe5\xa4\xaa\xe7\x99\xbd, wuse\n\xe5\x91\xb5\xe5\x91\xb5\n\xe6\x97\xa5\xe5\xa4\xa9'
"""

1.2 读取文件的方法

  • read() 将文件中的内容全部读取出来。弊端:占内存,如果文件过大,容易导致内存崩溃。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
f = open("动物世界.txt", mode="r", encoding="utf-8") 
content = f.read()
print(content)

#***************运行结果*****************
'''
东打一下西戳一下
动物未必需要尖牙
示爱的方法有礼貌或是我管它
要将情人一口吞下
还要显得温文尔雅
螳螂委屈的展示旧伤疤
......
'''
  • read(n) 读取n个字符。需要注意的是,如果再次读取,会在当前位置继续去读而不 是从头读。如果使用的是 rb 模式,则读取出来的是 n 个字节。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
f = open("../def/哇擦.txt", mode="r" encoding="utf-8") 
content = f.read(3)
print(content)
"""
结果:
友谊地
"""

f = open("../def/哇擦.txt", mode="rb")
content = f.read(3)
print(content)
"""
结果: b'\xe5\x8f\x8b'
"""

f = open("../def/哇擦.txt", mode="r", encoding="utf-8")
content = f.read(3)
content2 = f.read(3)
print(content)
print(content2)
"""
结果:
友谊地
久天长
"""
  • readline() ⼀次读取⼀行数据。注意: readline() 每次读取出来的数据都会有一 个 \n ,需要我们使用strip()方法来去掉 \n 或者空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
f = open("../def/哇擦.txt", mode="r", encoding="utf-8") 
content = f.readline()
content2 = f.readline()
content3 = f.readline()
content4 = f.readline()
content5 = f.readline()
content6 = f.readline()
print(content)
print(content2)
print(content3)
print(content4)
print(content5)
print(content6)
"""
结果:
友谊地久天长, 爱一点,
可惜我是水瓶座
一生中最爱
"""
  • readlines() 将所有的内容都逐行读取出来,放到一个列表中。容易出现内存崩溃的问题,不推荐使用。
1
2
3
4
5
f = open("../def/哇擦.txt", mode="r", encoding="utf-8") 
lst = f.readlines()
print(lst)
for line in lst:
print(line.strip())
  • 循环读取 每次读取一行内容,不会产生内存溢出的问题,推荐使用。
1
2
3
f = open("../def/哇擦.txt", mode="r", encoding="utf-8") 
for line in f:
print(line.strip())

二、只写模式

在该模式下,如果要写入的目标文件不存在,则会创建文件。 如果文件存在,则将原文件中的内容删除,再写入新内容。

2.1 不同的写入模式

  • w:正常写入
  • wb:二进制方式写入
1
2
3
4
5
f = open("小娃娃.txt", mode="w", encoding="utf-8") 
f.write("金毛狮王")
# f.read() not readable 模式是w,不可以执行读操作
f.flush() # 刷新,养成好习惯
f.close()

wb 模式下,可以不指定打开文件的编码,但是在写文件的时候,必须将字符串转化成 utf-8 的 bytes数据。

1
2
3
4
f = open("小娃娃.txt", mode="wb") 
f.write("金毛狮王".encode("utf-8"))
f.flush()
f.close()

三、追加模式

在追加模式下,我们写入的内容会追加在文件已有内容的结尾,不会对原始内容进行覆盖。

3.1 不同的追加模式

  • a:正常追加
  • ab:二进制方式追加
  • a+:追加读
1
2
3
4
5
6
7
8
9
10
11
12
f = open("小娃娃.txt", mode="a", encoding="utf-8") 
f.write("麻花藤的最爱")
f.flush()
f.close()

# a+模式下, 不论先读还是后读,都是读取不到数据的
f = open("小娃娃", mode="a+", encoding="utf-8")
f.write("马化腾")
content = f.read()
print(content)
f.flush()
f.close()

四、读写模式

对于读写模式,光标默认是在开头的,必须是先读再写。

4.1 不同的读写模式

  • r+:正常读写
  • r+b:二进制方式读写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 正确的使用方式
f = open("小娃娃.txt", mode="r+", encoding="utf-8")
content = f.read()
f.write("麻花藤的最爱")
print(content)
f.flush()
f.close()

# 错误的使用方式,会将开头的内容改写成"哈哈", 然后再读取后面的内容
f = open("⼩小娃娃", mode="r+", encoding="utf-8")
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()

五、写读模式

先将所有的内容清空,然后写入,最后读取。但是读取的内容是空的,不常用。

5.1 不同的写读模式

  • w+:正常写读
  • w+b:二进制方式写读
1
2
3
4
5
6
f = open("小娃娃", mode="w+", encoding="utf-8") 
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()

其他操作

一、光标移动

seek(n) 方法可以控制光标移动到 n 位置上。

注意:移动的单位是 byte,所以如果是 UTF-8 的中⽂,移动的值要是3的倍数。通常我们使⽤ seek 来使光标移动到开头或者结尾。

  • 移动到开头: seek(0)

  • 移动到结尾: seek(0, 2)

seek 的第二个参数表示的是从哪个位置进行偏移,默认是0,表示开头;1表⽰当前位置; 2表示结尾

1
2
3
4
5
6
7
8
9
10
11
f = open("小娃娃", mode="r+", encoding="utf-8") 
f.seek(0) # 光标移动到开头
content = f.read() # 读取内容, 此时光标移动到结尾
print(content)
f.seek(0) # 再次将光标移动到开头
f.seek(0, 2) # 将光标移动到结尾
content2 = f.read() # 读取内容,什么都没有
print(content2) f.seek(0) # 移动到开头
f.write("哈哈哈") # 写⼊信息,此时光标在9 中⽂文3 * 3个 = 9
f.flush()
f.close()

二、获取当前的光标位置

tell() 获取当前光标在什么位置

1
2
3
4
5
6
7
8
9
10
11
12
13
f = open("小娃娃", mode="r+", encoding="utf-8") 
f.seek(0) # 光标移动到开头
content = f.read() # 读取内容, 此时光标移动到结尾
print(content)
f.seek(0) # 再次将光标移动到开头
f.seek(0, 2) # 将光标移动到结尾
content2 = f.read() # 读取内容,什么都没有
print(content2)
f.seek(0) # 移动到开头
f.write("哈哈哈") # 写⼊入信息,此时光标在9 中⽂文3 * 3个 = 9
print(f.tell()) # 光标位置9
f.flush()
f.close()

三、文件截断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
f = open("小娃娃", mode="w", encoding="utf-8") 
f.write("哈哈") # 写⼊入两个字符
f.seek(3) # 光标移动到3, 也就是两个字中间
f.truncate() # 删掉光标后面的所有内容
f.close()


f = open("小娃娃", mode="r+", encoding="utf-8")
content = f.read(3) # 读取12个字符
f.seek(4) print(f.tell())
f.truncate() # 后面的所有内容全部都删掉 #
print(content)
f.flush()
f.close()

**注意:**在 r+ 模式下,如果读取了内容,不论读取内容多少,光标显示的是多少,再写入或者操作文件的时候都是在结尾进行的。所以如果想做截断操作,要先挪动光标到想要截断的位置,然后再进行截断。

关于 truncate(n),如果给出了n,则从开头进行截断;如果不给n,则从当前位置截断,后面的内容将会全部被删除。

四、with方法

为了避免打开文件后忘记关闭,可以通过管理上下文的方式操作文件,即:

1
2
with open('a.txt','r',encoding='utf-8') as f:
f.readline()

如此方式,当 with 代码块执行完毕时,内部会自动关闭并释放文件资源。with 支持同时对多个文件的上下文进行管理,即:

1
2
3
with open('a.txt','r',encoding='utf-8') as f_read, open('b.txt','w',encoding='utf-8') as f_write:     
f_read.readline()
f_write.write('hello')

Python 文件操作
https://clark-cdc.github.io/2019/03/21/0005-文件操作/
作者
clark
发布于
2019年3月21日
许可协议