为啥我不能在打开的文件上调用 read() 两次?
Posted
技术标签:
【中文标题】为啥我不能在打开的文件上调用 read() 两次?【英文标题】:Why can't I call read() twice on an open file?为什么我不能在打开的文件上调用 read() 两次? 【发布时间】:2011-04-23 19:08:27 【问题描述】:对于我正在进行的练习,我尝试使用read()
方法两次读取给定文件的内容。奇怪的是,当我第二次调用它时,它似乎没有将文件内容作为字符串返回?
这是代码
f = f.open()
# get the year
match = re.search(r'Popularity in (\d+)', f.read())
if match:
print match.group(1)
# get all the names
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', f.read())
if matches:
# matches is always None
当然我知道这不是最有效或最好的方法,这不是重点。关键是,为什么我不能给read()
打两次电话?我必须重置文件句柄吗?或者关闭/重新打开文件以执行此操作?
【问题讨论】:
您从哪里得到 read 不会改变文件状态的想法?您使用的是什么参考资料或教程? 我相信关闭和重新打开文件应该可以根据以下答案进行。 @Shynthriir:关闭并重新打开文件并不总是一个好主意,因为它可能会对系统产生其他影响(临时文件、incron 等)。 我只想声明一个显而易见的事实:您DID 调用了两次 read()! W/R/T/S.Lott,从 5 年开始:这确实需要在 python 文档中。显然,人们应该假设读取文件对象会改变任何东西的状态,特别是如果一个人习惯于使用不可变数据/函数式编程...... 【参考方案1】:调用read()
会读取整个文件并将读取光标留在文件末尾(没有更多内容可读取)。如果您希望一次读取一定数量的行,您可以使用readline()
、readlines()
或使用for line in handle:
遍历行。
要直接回答您的问题,一旦读取了文件,您可以使用read()
将读取光标返回到文件的开头(文档为here)。如果您知道文件不会太大,您还可以将read()
输出保存到一个变量中,在您的findall
表达式中使用它。
附言。完成后不要忘记关闭文件。
【讨论】:
+1,是的,请阅读临时变量以避免不必要的文件 I/O。这是一种虚假的经济,因为您的(显式)变量较少,所以您正在节省任何内存。 @NickT:我希望一个被多次读取的小文件会被操作系统缓存(至少在 Linux/OSX 上),所以不需要额外的文件 I/O 来读取两次。不适合内存的大文件不会被缓存,但您不想将它们读入变量,因为您将开始交换。因此,如有疑问,请务必多次阅读。如果您确定文件很小,请尽一切可能提供最好的程序。 可以使用with
自动拆除。【参考方案2】:
正如其他答案所建议的,您应该使用seek()
。
我只写一个例子:
>>> a = open('file.txt')
>>> a.read()
#output
>>> a.seek(0)
>>> a.read()
#same output
【讨论】:
【参考方案3】:到目前为止,回答这个问题的每个人都绝对正确 - read()
在文件中移动,所以在你调用它之后,你不能再次调用它。
我要补充的是,在您的特定情况下,您无需回到开头或重新打开文件,您只需将已读取的文本存储在局部变量中,然后使用它在您的程序中使用两次或多次:
f = f.open()
text = f.read() # read the file into a local variable
# get the year
match = re.search(r'Popularity in (\d+)', text)
if match:
print match.group(1)
# get all the names
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', text)
if matches:
# matches will now not always be None
【讨论】:
+1 实际上,这是本练习的建议解决方案 (code.google.com/intl/de-DE/edu/languages/google-python-class/…)。但不知何故,我没想过将字符串存储在变量中。哦! 对于 Python3,使用 pathlib。from pathlib import Path; text = Path(filename).read_text()
负责打开、关闭等操作。【参考方案4】:
我总是觉得阅读方法有点像在黑暗的小巷里散步。你往下走一点停下来,但如果你不计算你的步数,你就不确定你走了多远。 Seek 通过重新定位给出解决方案,另一个选项是 Tell,它返回文件中的位置。可能是 Python 文件 api 可以将 read 和 seek 结合到 read_from(position,bytes) 中以使其更简单——在这种情况发生之前,您应该阅读this page。
【讨论】:
【参考方案5】:read()
消费。因此,您可以重置文件,或者在重新阅读之前搜索到开始。或者,如果它适合您的任务,您可以使用 read(n)
仅消耗 n
字节。
【讨论】:
【参考方案6】:每个打开的文件都有一个关联的位置。
当您 read() 时,您从该位置读取。
例如,read(10)
从新打开的文件中读取前 10 个字节,然后另一个 read(10)
读取接下来的 10 个字节。
read()
不带参数读取文件的所有内容,将文件位置留在文件末尾。下次你打电话给read()
时,没有什么可读的了。
您可以使用seek
移动文件位置。或者在您的情况下可能更好的是做一个 read()
并保留两个搜索的结果。
【讨论】:
【参考方案7】:读取指针移动到最后读取的字节/字符之后。使用seek()
方法将读取指针回退到开头。
【讨论】:
以上是关于为啥我不能在打开的文件上调用 read() 两次?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的word excel 一次打不开,必须两次才能打开,在“打开”中选择文件可以打开。