@Ani l'autre message est de toute façon une copie de Insertion de ligne à la position spécifiée d'un fichier texte et il y a certainement des réponses claires et composées ici, pourquoi ne pas ajouter votre réponse ici au lieu de l'inverse? Une réponse acceptée n'est pas une exigence pour une bonne question.
Bhargav Rao
@BhargavRao Vote rétracté. J'aurais dû trouver ce duplicata!
Ani Menon
Réponses:
134
Malheureusement, il n'y a aucun moyen d'insérer au milieu d'un fichier sans le réécrire. Comme les affiches précédentes l'ont indiqué, vous pouvez ajouter à un fichier ou en écraser une partie en utilisant la recherche, mais si vous voulez ajouter des éléments au début ou au milieu, vous devrez le réécrire.
C'est une chose du système d'exploitation, pas une chose de Python. C'est la même chose dans toutes les langues.
Ce que je fais habituellement, c'est lire à partir du fichier, apporter les modifications et l'écrire dans un nouveau fichier appelé myfile.txt.tmp ou quelque chose comme ça. C'est mieux que de lire le fichier entier en mémoire car le fichier peut être trop volumineux pour cela. Une fois le fichier temporaire terminé, je le renomme de la même manière que le fichier d'origine.
C'est un bon moyen sûr de le faire, car si l'écriture du fichier se bloque ou s'interrompt pour une raison quelconque, vous avez toujours votre fichier d'origine intact.
Les outils Unix comme awk / sed font-ils quelque chose de similaire dans leur code?
Manish Gill
Ce n'est pas vrai que ce soit la même chose dans toutes les langues. Dans ActionScript: fileStream.openAsync (nom de fichier, FileMode.UPDATE); Ensuite, je peux aller n'importe où dans le fichier que je veux et changer quoi que ce soit.
AndrewBenjamin du
2
@AndrewBenjamin Savez-vous quel système appelle ActionScript? Y a-t-il une possibilité qu'openAsync lise le fichier et en écrive un nouveau après l'appel?
AlexLordThorsen
@Rawrgulmuffins, je ne le fais pas. Cependant, je sais qu'il ne lit pas le fichier entier en mémoire, car je l'ai utilisé pour gérer des tailles de fichiers de plusieurs Go. Je soupçonne que c'est la même chose que d'écrire avec C # streamwriter. Je considère python comme un outil pour faire de petites choses rapidement, plutôt que comme un développement à grande échelle et une manipulation de fichiers.
AndrewBenjamin
4
@AndrewBenjamin, l'utilisateur ne demande pas de chercher dans le fichier et de le modifier (toutes les langues que je connais peuvent le faire); il demande comment insérer du texte, ce qui est différent du simple changement / écrasement de ce qui se trouve déjà dans le fichier. Peut-être que dans l'application pratique, il est différent, mais rien que je puisse trouver dans l' API ActionScript n'indique qu'il se comporte différemment de tout autre langage à cet égard.
eestrada
104
Tout dépends de ce que tu veux faire. Pour ajouter, vous pouvez l'ouvrir avec "a":
with open("foo.txt","a")as f:
f.write("new line\n")
Si vous voulez préprendre quelque chose, vous devez d'abord lire le fichier:
with open("foo.txt","r+")as f:
old = f.read()# read everything in the file
f.seek(0)# rewind
f.write("new line\n"+ old)# write the new line before
Juste un petit ajout, pour utiliser l' withinstruction dans Python 2.5, vous devez ajouter "from future import with_statement". En dehors de cela, l'ouverture de fichiers avec l' withinstruction est certainement plus lisible et moins sujette aux erreurs que la fermeture manuelle.
Alexander Kojevnikov
2
Vous pouvez considérer la fileinputbibliothèque d'aide avec des manipulations de la routine dirty open / read / modify / write / replace bien lorsque vous utilisez inline=Truearg. Exemple ici: stackoverflow.com/a/2363893/47390
mikegreenberg
3
N'oubliez pas de fermer le fichier. f.Close()
D.Rosado
5
Ce n'est pas un style que j'utilise, D.Rosado, mais lorsque vous utilisez le style with, je ne pense pas que vous ayez besoin de fermer manuellement. Le avec garde une trace de la ressource qu'il crée.
Chris
4
Vous n'avez pas besoin de fermer manuellement le fichier. C'est tout l'intérêt d'utiliser "avec" ici. (Eh bien, en fait, Python le fait dès que l'objet fichier est ramassé, ce qui dans CPython se produit lorsque le nom qui lui est lié sort de la portée ... mais d'autres implémentations ne le font pas, et CPython pourrait arrêter de le faire un jour , donc "avec" est recommandé)
Jürgen A. Erhard
71
Le fileinputmodule de la bibliothèque standard Python réécrira un fichier en place si vous utilisez le paramètre inplace = 1:
import sysimport fileinput# replace all occurrences of 'sit' with 'SIT' and insert a line after the 5thfor i, line in enumerate(fileinput.input('lorem_ipsum.txt', inplace=1)):
sys.stdout.write(line.replace('sit','SIT'))# replace 'sit' and writeif i ==4: sys.stdout.write('\n')# write a blank line after the 5th line
Comment cela devrait-il fonctionner en python3? Je viens de porter une application qui contenait du code comme celui-ci de python à python3 et je ne pouvais tout simplement pas le faire fonctionner correctement. La variable «ligne» est un type d'octets, j'ai essayé de la décoder en unicode, puis de la modifier, puis de la coder en octets, mais cela ne fonctionnerait tout simplement pas correctement. Cela a soulevé une exception dont je ne me souviens pas du haut de ma tête. Les gens utilisent-ils fileinput inplace = 1 en python3 avec un succès?
Mais ce n'est pas un problème car vous l'avez testé d'abord sur un fichier sans importance?
Paula Livingstone
33
La réécriture d'un fichier sur place se fait souvent en enregistrant l'ancienne copie avec un nom modifié. Les gens d'Unix ajoutent un ~pour marquer l'ancien. Les gens de Windows font toutes sortes de choses - ajoutez .bak ou .old - ou renommez le fichier entièrement ou mettez le ~ au début du nom.
import shutil
shutil.move( afile, afile+"~")
destination= open( aFile,"w")
source= open( aFile+"~","r")for line in source:
destination.write( line )if<some condition>:
destination.write(>some additional line>+"\n")
source.close()
destination.close()
Au lieu de shutil, vous pouvez utiliser ce qui suit.
Cela semble bon. Vous vous demandez si .readlines () vaut mieux que d'itérer la source?
bozdoz
2
@bozdoz: il est préférable d'itérer puisque readlines lit tout le fichier. Pas bon pour les gros fichiers. Bien entendu, cela suppose que vous puissiez effectuer vos modifications de manière aussi localisée. Parfois, vous ne pouvez pas, ou votre code devient beaucoup plus compliqué.
Jürgen A. Erhard
@ S.Lott: os.rename(aFile, aFile + "~")modifiera le nom du fichier source, sans créer de copie.
Patapoom
14
Le module mmap de Python vous permettra d'insérer dans un fichier. L'exemple suivant montre comment cela peut être fait sous Unix (Windows mmap peut être différent). Notez que cela ne gère pas toutes les conditions d'erreur et que vous risquez de corrompre ou de perdre le fichier d'origine. De plus, cela ne gérera pas les chaînes Unicode.
import osfrom mmap import mmapdef insert(filename, str, pos):if len(str)<1:# nothing to insertreturn
f = open(filename,'r+')
m = mmap(f.fileno(), os.path.getsize(filename))
origSize = m.size()# or this could be an errorif pos > origSize:
pos = origSizeelif pos <0:
pos =0
m.resize(origSize + len(str))
m[pos+len(str):]= m[pos:origSize]
m[pos:pos+len(str)]= str
m.close()
f.close()
Il est également possible de le faire sans mmap avec des fichiers ouverts en mode `` r + '', mais c'est moins pratique et moins efficace car vous auriez à lire et à stocker temporairement le contenu du fichier de la position d'insertion à EOF - ce qui pourrait être énorme.
Comme mentionné par Adam, vous devez prendre en compte les limitations de votre système avant de pouvoir décider si vous avez suffisamment de mémoire pour tout lire en mémoire, remplacez-en des parties et réécrivez-le.
Si vous avez affaire à un petit fichier ou que vous n'avez pas de problèmes de mémoire, cela peut aider:
Option 1)
Lire le fichier entier en mémoire, faire une substitution regex sur tout ou partie de la ligne et le remplacer par cette ligne plus la ligne supplémentaire. Vous devrez vous assurer que la «ligne médiane» est unique dans le fichier ou si vous avez des horodatages sur chaque ligne, cela devrait être assez fiable.
# open file with r+b (allow write and binary mode)
f = open("file.log",'r+b')# read entire content of file into memory
f_content = f.read()# basically match middle line and replace it with itself and the extra line
f_content = re.sub(r'(middle line)', r'\1\nnew line', f_content)# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)# clear file content
f.truncate()# re-write the content with the updated content
f.write(f_content)# close file
f.close()
Option 2)
Calculez la ligne médiane et remplacez-la par cette ligne plus la ligne supplémentaire.
# open file with r+b (allow write and binary mode)
f = open("file.log",'r+b')# get array of lines
f_content = f.readlines()# get middle line
middle_line = len(f_content)/2# overwrite middle line
f_content[middle_line]+="\nnew line"# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)# clear file content
f.truncate()# re-write the content with the updated content
f.write(''.join(f_content))# close file
f.close()
Réponses:
Malheureusement, il n'y a aucun moyen d'insérer au milieu d'un fichier sans le réécrire. Comme les affiches précédentes l'ont indiqué, vous pouvez ajouter à un fichier ou en écraser une partie en utilisant la recherche, mais si vous voulez ajouter des éléments au début ou au milieu, vous devrez le réécrire.
C'est une chose du système d'exploitation, pas une chose de Python. C'est la même chose dans toutes les langues.
Ce que je fais habituellement, c'est lire à partir du fichier, apporter les modifications et l'écrire dans un nouveau fichier appelé myfile.txt.tmp ou quelque chose comme ça. C'est mieux que de lire le fichier entier en mémoire car le fichier peut être trop volumineux pour cela. Une fois le fichier temporaire terminé, je le renomme de la même manière que le fichier d'origine.
C'est un bon moyen sûr de le faire, car si l'écriture du fichier se bloque ou s'interrompt pour une raison quelconque, vous avez toujours votre fichier d'origine intact.
la source
Tout dépends de ce que tu veux faire. Pour ajouter, vous pouvez l'ouvrir avec "a":
Si vous voulez préprendre quelque chose, vous devez d'abord lire le fichier:
la source
with
instruction dans Python 2.5, vous devez ajouter "from future import with_statement". En dehors de cela, l'ouverture de fichiers avec l'with
instruction est certainement plus lisible et moins sujette aux erreurs que la fermeture manuelle.fileinput
bibliothèque d'aide avec des manipulations de la routine dirty open / read / modify / write / replace bien lorsque vous utilisezinline=True
arg. Exemple ici: stackoverflow.com/a/2363893/47390f.Close()
Le
fileinput
module de la bibliothèque standard Python réécrira un fichier en place si vous utilisez le paramètre inplace = 1:la source
La réécriture d'un fichier sur place se fait souvent en enregistrant l'ancienne copie avec un nom modifié. Les gens d'Unix ajoutent un
~
pour marquer l'ancien. Les gens de Windows font toutes sortes de choses - ajoutez .bak ou .old - ou renommez le fichier entièrement ou mettez le ~ au début du nom.Au lieu de
shutil
, vous pouvez utiliser ce qui suit.la source
os.rename(aFile, aFile + "~")
modifiera le nom du fichier source, sans créer de copie.Le module mmap de Python vous permettra d'insérer dans un fichier. L'exemple suivant montre comment cela peut être fait sous Unix (Windows mmap peut être différent). Notez que cela ne gère pas toutes les conditions d'erreur et que vous risquez de corrompre ou de perdre le fichier d'origine. De plus, cela ne gérera pas les chaînes Unicode.
Il est également possible de le faire sans mmap avec des fichiers ouverts en mode `` r + '', mais c'est moins pratique et moins efficace car vous auriez à lire et à stocker temporairement le contenu du fichier de la position d'insertion à EOF - ce qui pourrait être énorme.
la source
Comme mentionné par Adam, vous devez prendre en compte les limitations de votre système avant de pouvoir décider si vous avez suffisamment de mémoire pour tout lire en mémoire, remplacez-en des parties et réécrivez-le.
Si vous avez affaire à un petit fichier ou que vous n'avez pas de problèmes de mémoire, cela peut aider:
Option 1) Lire le fichier entier en mémoire, faire une substitution regex sur tout ou partie de la ligne et le remplacer par cette ligne plus la ligne supplémentaire. Vous devrez vous assurer que la «ligne médiane» est unique dans le fichier ou si vous avez des horodatages sur chaque ligne, cela devrait être assez fiable.
Option 2) Calculez la ligne médiane et remplacez-la par cette ligne plus la ligne supplémentaire.
la source
A écrit une petite classe pour faire ça proprement.
Ensuite, vous pouvez l'utiliser de cette façon:
la source
Si vous connaissez unix, vous pouvez essayer ce qui suit:
Notes: $ signifie l'invite de commande
Supposons que vous ayez un fichier my_data.txt avec un contenu en tant que tel:
Ensuite, en utilisant le
os
module, vous pouvez utiliser lessed
commandes habituellesSi vous n'êtes pas au courant de sed, vérifiez-le, il est extrêmement utile.
la source