@Ani der andere Beitrag ist sowieso ein Duplikat des Einfügens einer Zeile an der angegebenen Position einer Textdatei, und sicherlich gibt es hier klar zusammengesetzte Antworten. Warum fügen Sie Ihre Antwort hier nicht statt andersherum hinzu? Eine akzeptierte Antwort ist keine Voraussetzung für eine gute Frage.
Bhargav Rao
@ BhargavRao Abstimmung zurückgezogen. Ich hätte dieses Duplikat allerdings finden sollen!
Ani Menon
Antworten:
134
Leider gibt es keine Möglichkeit, in die Mitte einer Datei einzufügen, ohne sie neu zu schreiben. Wie in früheren Postern angegeben, können Sie eine Datei anhängen oder einen Teil davon mit search überschreiben. Wenn Sie jedoch am Anfang oder in der Mitte Inhalte hinzufügen möchten, müssen Sie diese neu schreiben.
Dies ist eine Betriebssystemsache, keine Python-Sache. Es ist in allen Sprachen gleich.
Normalerweise lese ich aus der Datei, nehme die Änderungen vor und schreibe sie in eine neue Datei namens myfile.txt.tmp oder ähnliches. Dies ist besser als das Einlesen der gesamten Datei in den Speicher, da die Datei möglicherweise zu groß dafür ist. Sobald die temporäre Datei fertig ist, benenne ich sie genauso um wie die Originaldatei.
Dies ist ein guter und sicherer Weg, denn wenn der Dateischreibvorgang aus irgendeinem Grund abstürzt oder abgebrochen wird, haben Sie immer noch Ihre unberührte Originaldatei.
Tun Unix-Tools wie awk / sed etwas Ähnliches in ihrem Code?
Manish Gill
Es ist nicht wahr, dass dies in allen Sprachen gleich ist. In ActionScript: fileStream.openAsync (Dateiname, FileMode.UPDATE); Dann kann ich überall in der gewünschten Datei etwas ändern.
AndrewBenjamin
2
@AndrewBenjamin Wissen Sie, welche Systemaufrufe ActionScript macht? Gibt es eine Möglichkeit, dass openAsync die Datei liest und nach dem Aufruf eine neue schreibt?
AlexLordThorsen
@Rawrgulmuffins mache ich nicht. Ich weiß jedoch, dass nicht die gesamte Datei in den Speicher eingelesen wird, da ich damit Dateigrößen von mehreren GB verarbeitet habe. Ich vermute, es ist dasselbe wie mit C # Streamwriter zu schreiben. Ich betrachte Python als ein Werkzeug, um kleine Dinge schnell zu erledigen, anstatt große Entwicklung und Dateimanipulation.
AndrewBenjamin
4
@AndrewBenjamin, der Benutzer fragt nicht danach, in der Datei herumzusuchen und sie zu ändern (jede Sprache, die ich kenne, kann das); Er fragt nach dem Einfügen von Text, was sich von dem einfachen Ändern / Überschreiben der bereits in der Datei enthaltenen Elemente unterscheidet. Vielleicht ist es in der praktischen Anwendung anders, aber nichts, was ich in der ActionScript-API finden kann, weist darauf hin, dass es sich in dieser Hinsicht anders verhält als jede andere Sprache.
Eestrada
104
Kommt darauf an, was du machen willst. Zum Anhängen können Sie es mit "a" öffnen:
with open("foo.txt","a")as f:
f.write("new line\n")
Wenn Sie etwas vorgeben möchten, müssen Sie zuerst aus der Datei lesen:
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
Nur eine kleine Ergänzung, um die withAnweisung in Python 2.5 zu verwenden, müssen Sie "from future import with_statement" hinzufügen. Abgesehen davon ist das Öffnen von Dateien mit der withAnweisung definitiv lesbarer und weniger fehleranfällig als das manuelle Schließen.
Alexander Kojevnikov
2
Sie könnten die fileinputHelfer-Bibliothek mit Handles für die schmutzige Routine zum Öffnen / Lesen / Ändern / Schreiben / Ersetzen in Betracht ziehen , wenn Sie das inline=TrueArgument verwenden. Beispiel hier: stackoverflow.com/a/2363893/47390
mikegreenberg
3
Vergessen Sie nicht, die Datei zu schließen. f.Close()
D. Rosado
5
Es ist kein Stil, den ich verwende, D.Rosado, aber wenn Sie den with-Stil verwenden, müssen Sie ihn nicht manuell schließen. Das with verfolgt die Ressource, die es erstellt.
Chris
4
Sie müssen die Datei nicht manuell schließen. Das ist der springende Punkt bei der Verwendung von "mit" hier. (Nun, tatsächlich tut Python dies, sobald das Dateiobjekt durch Müll gesammelt wurde, was in CPython passiert, wenn der daran gebundene Name den Gültigkeitsbereich verlässt ... aber andere Implementierungen tun dies nicht und CPython hört möglicherweise eines Tages damit auf , also "mit" wird empfohlen)
Jürgen A. Erhard
71
Das fileinputModul der Python-Standardbibliothek schreibt eine Datei neu, wenn Sie den Parameter inplace = 1 verwenden:
import sys
import 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
Wie soll das in Python3 funktionieren? Ich habe gerade eine App portiert, die Code wie diesen von Python auf Python3 hatte, und ich konnte dies einfach nicht richtig zum Laufen bringen. Die 'line'-Variable ist ein Bytetyp. Ich habe versucht, sie in Unicode zu dekodieren und sie dann zu ändern und dann wieder in Bytes zu kodieren, aber es würde einfach nicht richtig funktionieren. Es gab einige Ausnahmen, an die ich mich nicht mehr erinnern kann. Verwenden Leute, die in Python3 den Dateieingang inplace = 1 verwenden, mit Erfolg?
Aber es ist kein Problem, denn Sie haben es zuerst an einer unwichtigen Datei getestet, oder?
Paula Livingstone
33
Das Umschreiben einer Datei erfolgt häufig durch Speichern der alten Kopie unter einem geänderten Namen. Unix-Leute fügen ein hinzu ~, um das alte zu markieren. Windows-Leute machen alle möglichen Dinge - fügen Sie .bak oder .old hinzu - oder benennen Sie die Datei vollständig um oder setzen Sie das ~ auf die Vorderseite des Namens.
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()
Sieht gut aus. Sie fragen sich, ob .readlines () besser ist als die Quelle zu iterieren?
Bozdoz
2
@bozdoz: Iterieren ist besser, da readlines die gesamte Datei liest. Nicht gut für große Dateien. Dies setzt natürlich voraus, dass Sie Ihre Änderungen auf eine so lokalisierte Weise vornehmen können. Manchmal können Sie nicht oder Ihr Code wird viel komplizierter.
Jürgen A. Erhard
@ S.Lott: Ändert os.rename(aFile, aFile + "~")den Namen der Quelldatei und erstellt keine Kopie.
Patapoom
14
Mit dem mmap-Modul von Python können Sie in eine Datei einfügen. Das folgende Beispiel zeigt, wie dies unter Unix durchgeführt werden kann (Windows mmap kann unterschiedlich sein). Beachten Sie, dass dies nicht alle Fehlerbedingungen behandelt und Sie möglicherweise die Originaldatei beschädigen oder verlieren. Dies behandelt auch keine Unicode-Zeichenfolgen.
import os
from mmap import mmap
def 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 = origSize
elif 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()
Es ist auch möglich, dies ohne mmap mit Dateien zu tun, die im 'r +' - Modus geöffnet sind. Dies ist jedoch weniger bequem und weniger effizient, da Sie den Inhalt der Datei von der Einfügeposition in EOF lesen und vorübergehend speichern müssten sei riesig.
Wie von Adam erwähnt, müssen Sie Ihre Systembeschränkungen berücksichtigen, bevor Sie entscheiden können, ob Sie über genügend Speicher verfügen, um alles in den Speicher einzulesen, Teile davon zu ersetzen und neu zu schreiben.
Wenn Sie mit einer kleinen Datei arbeiten oder keine Speicherprobleme haben, kann dies helfen:
Option 1)
Lesen Sie die gesamte Datei in den Speicher, ersetzen Sie die gesamte Zeile oder einen Teil der Zeile durch Regex und ersetzen Sie sie durch diese Zeile plus die zusätzliche Zeile. Sie müssen sicherstellen, dass die 'mittlere Zeile' in der Datei eindeutig ist. Wenn Sie in jeder Zeile Zeitstempel haben, sollte dies ziemlich zuverlässig sein.
# 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)
Finden Sie die mittlere Linie heraus und ersetzen Sie sie durch diese Linie plus die zusätzliche Linie.
# 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()
Antworten:
Leider gibt es keine Möglichkeit, in die Mitte einer Datei einzufügen, ohne sie neu zu schreiben. Wie in früheren Postern angegeben, können Sie eine Datei anhängen oder einen Teil davon mit search überschreiben. Wenn Sie jedoch am Anfang oder in der Mitte Inhalte hinzufügen möchten, müssen Sie diese neu schreiben.
Dies ist eine Betriebssystemsache, keine Python-Sache. Es ist in allen Sprachen gleich.
Normalerweise lese ich aus der Datei, nehme die Änderungen vor und schreibe sie in eine neue Datei namens myfile.txt.tmp oder ähnliches. Dies ist besser als das Einlesen der gesamten Datei in den Speicher, da die Datei möglicherweise zu groß dafür ist. Sobald die temporäre Datei fertig ist, benenne ich sie genauso um wie die Originaldatei.
Dies ist ein guter und sicherer Weg, denn wenn der Dateischreibvorgang aus irgendeinem Grund abstürzt oder abgebrochen wird, haben Sie immer noch Ihre unberührte Originaldatei.
quelle
Kommt darauf an, was du machen willst. Zum Anhängen können Sie es mit "a" öffnen:
Wenn Sie etwas vorgeben möchten, müssen Sie zuerst aus der Datei lesen:
quelle
with
Anweisung in Python 2.5 zu verwenden, müssen Sie "from future import with_statement" hinzufügen. Abgesehen davon ist das Öffnen von Dateien mit derwith
Anweisung definitiv lesbarer und weniger fehleranfällig als das manuelle Schließen.fileinput
Helfer-Bibliothek mit Handles für die schmutzige Routine zum Öffnen / Lesen / Ändern / Schreiben / Ersetzen in Betracht ziehen , wenn Sie dasinline=True
Argument verwenden. Beispiel hier: stackoverflow.com/a/2363893/47390f.Close()
Das
fileinput
Modul der Python-Standardbibliothek schreibt eine Datei neu, wenn Sie den Parameter inplace = 1 verwenden:quelle
Das Umschreiben einer Datei erfolgt häufig durch Speichern der alten Kopie unter einem geänderten Namen. Unix-Leute fügen ein hinzu
~
, um das alte zu markieren. Windows-Leute machen alle möglichen Dinge - fügen Sie .bak oder .old hinzu - oder benennen Sie die Datei vollständig um oder setzen Sie das ~ auf die Vorderseite des Namens.Stattdessen
shutil
können Sie Folgendes verwenden.quelle
os.rename(aFile, aFile + "~")
den Namen der Quelldatei und erstellt keine Kopie.Mit dem mmap-Modul von Python können Sie in eine Datei einfügen. Das folgende Beispiel zeigt, wie dies unter Unix durchgeführt werden kann (Windows mmap kann unterschiedlich sein). Beachten Sie, dass dies nicht alle Fehlerbedingungen behandelt und Sie möglicherweise die Originaldatei beschädigen oder verlieren. Dies behandelt auch keine Unicode-Zeichenfolgen.
Es ist auch möglich, dies ohne mmap mit Dateien zu tun, die im 'r +' - Modus geöffnet sind. Dies ist jedoch weniger bequem und weniger effizient, da Sie den Inhalt der Datei von der Einfügeposition in EOF lesen und vorübergehend speichern müssten sei riesig.
quelle
Wie von Adam erwähnt, müssen Sie Ihre Systembeschränkungen berücksichtigen, bevor Sie entscheiden können, ob Sie über genügend Speicher verfügen, um alles in den Speicher einzulesen, Teile davon zu ersetzen und neu zu schreiben.
Wenn Sie mit einer kleinen Datei arbeiten oder keine Speicherprobleme haben, kann dies helfen:
Option 1) Lesen Sie die gesamte Datei in den Speicher, ersetzen Sie die gesamte Zeile oder einen Teil der Zeile durch Regex und ersetzen Sie sie durch diese Zeile plus die zusätzliche Zeile. Sie müssen sicherstellen, dass die 'mittlere Zeile' in der Datei eindeutig ist. Wenn Sie in jeder Zeile Zeitstempel haben, sollte dies ziemlich zuverlässig sein.
Option 2) Finden Sie die mittlere Linie heraus und ersetzen Sie sie durch diese Linie plus die zusätzliche Linie.
quelle
Schrieb eine kleine Klasse dafür sauber.
Dann können Sie es folgendermaßen verwenden:
quelle
Wenn Sie Unix kennen, können Sie Folgendes versuchen:
Anmerkungen: $ bedeutet die Eingabeaufforderung
Angenommen, Sie haben eine Datei my_data.txt mit Inhalten als solchen:
Dann können Sie mit dem
os
Modul die üblichensed
Befehle verwendenWenn Sie sich sed nicht bewusst sind, probieren Sie es aus, es ist äußerst nützlich.
quelle