Why can't I call read() twice on an open file?

2018-12-31 01:06发布

For an exercise I'm doing, I'm trying to read the contents of a given file twice using the read() method. Strangely, when I call it the second time, it doesn't seem to return the file content as a string?

Here's the code

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

Of course I know that this is not the most efficient or best way, this is not the point here. The point is, why can't I call read() twice? Do I have to reset the file handle? Or close / reopen the file in order to do that?

标签: python io
7条回答
墨雨无痕
2楼-- · 2018-12-31 01:39

Every open file has an associated position.
When you read() you read from that position. For example read(10) reads the first 10 bytes from a newly opened file, then another read(10) reads the next 10 bytes. read() without arguments reads all of the contents of the file, leaving the file position at the end of the file. Next time you call read() there is nothing to read.

You can use seek to move the file position. Or probably better in your case would be to do one read() and keep the result for both searches.

查看更多
几人难应
3楼-- · 2018-12-31 01:40

Everyone who has answered this question so far is absolutely right - read() moves through the file, so after you've called it, you can't call it again.

What I'll add is that in your particular case, you don't need to seek back to the start or reopen the file, you can just store the text that you've read in a local variable, and use it twice, or as many times as you like, in your program:

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
查看更多
何处买醉
4楼-- · 2018-12-31 01:41

yeah, as above...

i'll write just an example:

>>> a = open('file.txt')
>>> a.read()
#output
>>> a.seek(0)
>>> a.read()
#same output
查看更多
骚的不知所云
5楼-- · 2018-12-31 01:41

read() consumes. So, you could reset the file, or seek to the start before re-reading. Or, if it suites your task, you can use read(n) to consume only n bytes.

查看更多
几人难应
6楼-- · 2018-12-31 01:52

Calling read() reads through the entire file and leaves the read cursor at the end of the file (with nothing more to read). If you are looking to read a certain number of lines at a time you could use readline(), readlines() or iterate through lines with for line in handle:.

To answer your question directly, once a file has been read, with read() you can use seek(0) to return the read cursor to the start of the file (docs are here). If you know the file isn't going to be too large, you can also save the read() output to a variable, using it in your findall expressions.

Ps. Dont forget to close the file after you are done with it ;)

查看更多
梦醉为红颜
7楼-- · 2018-12-31 01:59

The read pointer moves to after the last read byte/character. Use the seek() method to rewind the read pointer to the beginning.

查看更多
登录 后发表回答