我的博客

修改文件,而不重写不变部分

目录
  1. 修改
  2. 截断

使用 ‘r+’ 参数打开文件,定位文件指针到指定位置然后修改即可。这是写入内容将覆盖原位置的内容,原来其他的内容将保持不变。但是如果修改内容与原内容长度不同时无法采取这种方法。 假设有这样的任务,2亿行的文件每行只有一个a,需要把第三行的a改为b。 使用python的做法(另附两种其他的方法,一种python读取在全部重新写入,一种awk) 1、生成测试文件:

修改

一个2亿行的文件 test_file,每行都只有一个a。文件大小382M。

1
2
3
4
f = open('test_file', 'w')
for i in range(200000000):
f.write('a\n')
f.close()

运行时间 45.916s

2、测试

(1)用r+参数读原文件,直接在原文件上修改

1
2
3
4
5
import os
f = open('test_file', 'r+')
f.seek(4)
f.write('b')
f.close()

运行时间 0m0.014s

(2)读原文件,然后把改动后的结果写入另一个文件:

1
2
3
4
5
6
7
8
9
10
11
fr = open('test_file', 'r')
fw = open('test_file_mod', 'w')
i = 0
for l in fr:
i += 1
if i == 3:
fw.write('b\n')
else:
fw.write(l)
fr.close()
fw.close()

运行时间 1m35.701s

(3)用awk把输出结果到新文件

1
awk '{if(NR==3){print "b"}else{print}}' test_file > test_file_mod

运行时间0m36.397s

使用time命令测试执行时间(取real时间)。三种方法对内存消耗都很小。时间消耗差别很大主要是使用w+时仅写入改动部分,磁盘IO量比另两种方法小很多。 另外测试了使用python按行读完整个test_file的时间是 0m42.689s。 测试使用的代码如下:

1
2
3
4
5
f = open('test_file')
while True:
l = f.readline()
if not l: break
f.close()

在阿里云ECS上进行测试CPU为Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz

我在知乎的回答:https://www.zhihu.com/answer/605322220

截断

2020 / 04 / 14 更新

今天又遇到一个问题:

一个很大的文件,例如 5 千万行,每行是一个字符 a 。 想删掉最后一行。

重新写入前面不要删除的行,耗时很多。

*

我在 v2ex 的提问:https://www.v2ex.com/t/662192#reply5

根据 @tabris17 的方法,用 python3 实现是:

1
2
3
4
import os
f = os.open('test_file', os.O_RDWR|os.O_CREAT)
os.ftruncate(f, os.path.getsize('test_file') - 2)
os.close(f)

附实验代码:

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
t0 = time.time()
with open('test_file', 'w') as f:
for i in range(50000000):
f.write('a\n')
t1 = time.time()
t1 - t0 # 11.500069618225098
# !wc -l test_file # 50000000

# 重新写入
t0 = time.time()
with open('test_file', 'w') as f:
for i in range(50000000-1):
f.write('a\n')
t1 = time.time()
t1 - t0 # 11.542783975601196
# !wc -l test_file # 49999999

import os
t0 = time.time()
f = os.open('test_file', os.O_RDWR|os.O_CREAT)
os.ftruncate(f, os.path.getsize('test_file') - 2)
os.close(f)
t1 = time.time()
t1 - t0 # 0.000209808349609375
# !wc -l test_file # 49999998

实验环境: Intel(R) Xeon(R) Gold 6161 CPU @ 2.20GHz

评论无需登录,可以匿名,欢迎评论!