web-dev-qa-db-fra.com

Pourquoi ne puis-je pas appeler read () deux fois sur un fichier ouvert?

Pour un exercice que je fais, j'essaie de lire le contenu d'un fichier donné deux fois en utilisant la méthode read(). Étrangement, quand je l'appelle la deuxième fois, il ne semble pas renvoyer le contenu du fichier sous forme de chaîne?

Voici le 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

Bien sûr, je sais que ce n'est pas le moyen le plus efficace ou le meilleur, ce n'est pas le point ici. Le fait est, pourquoi ne puis-je pas appeler read() deux fois? Dois-je réinitialiser le descripteur de fichier? Ou fermer/rouvrir le fichier pour ce faire?

85
helpermethod

L'appel de read() lit tout le fichier et laisse le curseur de lecture à la fin du fichier (sans rien de plus à lire). Si vous cherchez à lire un certain nombre de lignes à la fois, vous pouvez utiliser readline(), readlines() ou parcourir les lignes avec for line in handle:.

Pour répondre directement à votre question, une fois un fichier lu, avec read() vous pouvez utiliser seek(0) pour ramener le curseur de lecture au début du fichier (les documents sont ici ). Si vous savez que le fichier ne sera pas trop volumineux, vous pouvez également enregistrer la sortie read() dans une variable, en l'utilisant dans vos expressions findall.

Ps. N'oubliez pas de fermer le fichier une fois que vous en avez terminé;)

135
Tim

oui, comme ci-dessus ...

je vais écrire juste un exemple:

>>> a = open('file.txt')
>>> a.read()
#output
>>> a.seek(0)
>>> a.read()
#same output
24
Ant

Tous ceux qui ont répondu à cette question jusqu'à présent ont tout à fait raison - read() parcourt le fichier, donc après l'avoir appelé, vous ne pouvez plus le rappeler.

Ce que j'ajouterai, c'est que dans votre cas particulier, vous n'avez pas besoin de revenir au début ou de rouvrir le fichier, vous pouvez simplement stocker le texte que vous avez lu dans une variable locale, et l'utiliser deux fois, ou autant de fois que vous le souhaitez, dans votre programme:

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
16
Tom Anderson

Le pointeur de lecture se déplace après le dernier octet/caractère lu. Utilisez la méthode seek() pour rembobiner le pointeur de lecture au début.

14

Chaque fichier ouvert a une position associée.
Lorsque vous lisez (), vous lisez à partir de cette position. Par exemple, read(10) lit les 10 premiers octets d'un fichier nouvellement ouvert, puis un autre read(10) lit les 10 octets suivants. read() sans argument lit tout le contenu du fichier, laissant la position du fichier à la fin du fichier. La prochaine fois que vous appellerez read(), il n'y aura rien à lire.

Vous pouvez utiliser seek pour déplacer la position du fichier. Ou mieux dans votre cas serait de faire une read() et de conserver le résultat pour les deux recherches.

2
Douglas Leeder

Je trouve toujours la méthode de lecture quelque chose d'une promenade dans une ruelle sombre. Vous descendez un peu et vous vous arrêtez mais si vous ne comptez pas vos pas, vous n'êtes pas sûr de votre chemin. Seek donne la solution en repositionnant, l'autre option est Tell qui renvoie la position le long du fichier. Peut être le Python api peut combiner lecture et recherche dans un read_from (position, octets) pour le rendre plus simple - jusqu'à ce que cela se produise, vous devriez lire cette page .

1
whatnick

read() consomme. Ainsi, vous pouvez réinitialiser le fichier, ou rechercher au début avant de relire. Ou, s'il convient à votre tâche, vous pouvez utiliser read(n) pour ne consommer que n octets.

1
towi