Почему я не могу дважды вызвать read () для открытого файла? - PullRequest
83 голосов
/ 11 октября 2010

Для упражнения, которое я выполняю, я пытаюсь прочитать содержимое данного файла дважды, используя метод 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() дважды? Должен ли я сбросить дескриптор файла? Или закрыть / открыть файл, чтобы сделать это?

Ответы [ 7 ]

133 голосов
/ 11 октября 2010

Вызов read() читает весь файл и оставляет курсор чтения в конце файла (больше нечего читать).Если вы хотите прочитать определенное количество строк за раз, вы можете использовать readline(), readlines() или перебирать строки с помощью for line in handle:.

Чтобы ответить на ваш вопрос напрямую, после того, как файл былread, с read() вы можете использовать seek(0), чтобы вернуть курсор чтения в начало файла (здесь документы ).Если вы знаете, что файл не будет слишком большим, вы также можете сохранить вывод read() в переменную, используя его в выражениях findall.

Ps.Не забудьте закрыть файл после того, как с ним покончим;)

22 голосов
/ 11 октября 2010

да, как указано выше ...

я напишу только пример:

>>> a = open('file.txt')
>>> a.read()
#output
>>> a.seek(0)
>>> a.read()
#same output
16 голосов
/ 11 октября 2010

Каждый, кто до сих пор ответил на этот вопрос, абсолютно прав - 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
14 голосов
/ 11 октября 2010

Указатель чтения перемещается после последнего прочитанного байта / символа.Используйте метод seek() для перемотки указателя чтения на начало.

2 голосов
/ 11 октября 2010

Каждый открытый файл имеет соответствующую позицию.
Когда вы читаете (), вы читаете с этой позиции. Например, read(10) читает первые 10 байтов из вновь открытого файла, затем другой read(10) читает следующие 10 байтов. read() без аргументов читает все содержимое файла, оставляя позицию файла в конце файла. В следующий раз, когда вы позвоните read(), читать нечего.

Вы можете использовать seek для перемещения позиции файла. Или, возможно, лучше в вашем случае сделать один read() и сохранить результат для обоих поисков.

1 голос
/ 11 октября 2010

Я всегда нахожу метод чтения чем-то вроде прогулки по темному переулку.Вы немного спускаетесь и останавливаетесь, но если вы не считаете свои шаги, вы не знаете, как далеко вы продвинулись.Seek дает решение путем изменения положения, другой вариант - Tell, который возвращает позицию вдоль файла.Может быть, файл Python api может объединить чтение и поиск в read_from (позиция, байты), чтобы упростить его - пока это не произойдет, вы должны прочитать эту страницу .

1 голос
/ 11 октября 2010

read() потребляет .Таким образом, вы можете сбросить файл или найти до начала перед повторным чтением.Или, если это подходит вашей задаче, вы можете использовать read(n), чтобы использовать только n байт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...