ead*_*ead 4 python file truncation python-2.7 python-3.x
当一个新手(像我一样)要求在python中读取/处理文本文件时,他经常得到如下答案:
with open("input.txt", 'r') as f:
for line in f:
#do your stuff
Run Code Online (Sandbox Code Playgroud)
现在我想在特殊行之后截断我正在阅读的文件中的所有内容.修改上面的例子后,我使用:
with open("input.txt", 'r+') as file:
for line in file:
print line.rstrip("\n\r") #for debug
if line.rstrip("\n\r")=="CC":
print "truncating!" #for debug
file.truncate();
break;
Run Code Online (Sandbox Code Playgroud)
并期望它在看到第一个"CC"之后扔掉所有东西.在input.txt上运行此代码:
AA
CC
DD
Run Code Online (Sandbox Code Playgroud)
控制台上打印以下内容(如预期):
AA
CC
truncating!
Run Code Online (Sandbox Code Playgroud)
但文件"input.txt"保持不变!?!?
怎么可能?我做错了什么?
编辑:操作后我希望文件包含:
AA
CC
Run Code Online (Sandbox Code Playgroud)
看起来你正在成为Python内部使用的预读缓冲区的牺牲品.从file.next()方法的文档:
文件对象是它自己的迭代器,例如
iter(f)
返回f(除非f被关闭).当文件用作迭代器时,通常在for
循环中(例如,for line in f: print line.strip()
),next()
重复调用该方法.此方法返回下一个输入行,或者StopIteration
当文件打开以供读取时触发EOF时引发(当文件打开以进行写入时行为未定义).为了使for
循环成为循环文件行的最有效方式(一种非常常见的操作),该next()
方法使用隐藏的预读缓冲区.由于使用预读缓冲区,next()
与其他文件方法(如readline()
)结合使用是行不通的.但是,使用seek()
将文件重新定位到绝对位置将刷新预读缓冲区.
结果是文件的位置不是你在截断时所期望的位置.解决这个问题的一种方法是使用readline
循环文件而不是迭代器:
line = file.readline()
while line:
...
line = file.readline()
Run Code Online (Sandbox Code Playgroud)
除了 glibdud 的答案之外, truncate() 还需要删除内容的位置的大小。您可以通过命令获取文件中的当前位置tell()
。正如他提到的,通过使用 for 循环,next()
可以禁止像tell 这样的命令。但在建议的 while 循环中,您可以在当前的tell() 位置截断。所以完整的代码如下所示:
Python 3:
with open("test.txt", 'r+') as file:
line = file.readline()
while line:
print(line.strip())
if line.strip() == "CC":
print("truncating")
file.truncate(file.tell())
break
line = file.readline()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
768 次 |
最近记录: |