Ich benutze Python und möchte eine Zeichenfolge in eine Textdatei einfügen, ohne die Datei zu löschen oder zu kopieren. Wie kann ich das machen?Wie man eine Textdatei ändert?
Antwort
Hängt davon ab, was Sie tun möchten. Anhängen Sie es mit „a“ öffnen:
with open("foo.txt", "a") as f:
f.write("new line\n")
Wenn Sie etwas, das Sie preprend haben aus der Datei lesen Sie zuerst:
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 ein kleiner Zusatz, um die 'with'-Anweisung in Python 2.5 zu verwenden, müssen Sie "from __future__ import with_statement" hinzufügen. Außerdem ist das Öffnen von Dateien mit der Anweisung 'with' deutlich lesbarer und weniger fehleranfällig als das manuelle Schließen. –
Sie könnten die 'libinput'-Hilfebibliothek in Betracht ziehen, die die schmutzige open/read/modify/write/replace-Routine gut verarbeitet, wenn Sie das' inline = True'-Argument verwenden. Beispiel hier: http://stackoverflow.com/a/2363893/47390 – mikegreenberg
Vergessen Sie nicht, die Datei zu schließen. 'f.Close()' –
Leider gibt es keine Möglichkeit, in der Mitte einfügen einer Datei, ohne sie neu zu schreiben. Wie vorherige Poster gezeigt haben, können Sie eine Datei anhängen oder einen Teil davon mit Hilfe von seek überschreiben, aber wenn Sie am Anfang oder in der Mitte etwas hinzufügen möchten, müssen Sie es neu schreiben.
Dies ist eine Betriebssystem-Sache, keine Python-Sache. Es ist in allen Sprachen gleich.
Normalerweise lese ich aus der Datei, mache die Änderungen und schreibe sie in eine neue Datei namens myfile.txt.tmp oder so ähnlich. Dies ist besser als das Lesen der gesamten Datei in den Speicher, weil die Datei dafür möglicherweise zu groß ist. Sobald die temporäre Datei fertig ist, benenne ich sie genauso wie die ursprüngliche Datei.
Dies ist ein guter, sicherer Weg, um es zu tun, denn wenn die Datei schreiben abstürzt oder aus irgendeinem Grund abbricht, haben Sie immer noch Ihre unberührte Originaldatei.
Tun Unix-Tools wie awk/sed etwas ähnliches in ihrem Code? –
Es ist nicht wahr, dass dies in allen Sprachen gleich ist. In ActionScript: fileStream.openAsync (Dateiname, FileMode.UPDATE); Dann kann ich irgendwo in die Datei gehen, die ich will und alles ändern. – AndrewBenjamin
@AndrewBenjamin Weißt du, welches System ruft ActionScript auf? Besteht die Möglichkeit, dass openAsync die Datei liest und nach dem Aufruf eine neue schreibt? – AlexLordThorsen
Das Umschreiben einer Datei wird häufig durch Speichern der alten Kopie mit einem geänderten Namen durchgeführt. 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 die ~ 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()
Statt shutil
, können Sie die folgenden.
import os
os.rename(aFile, aFile+"~")
Sieht gut aus. Sie fragen sich, ob .readlines() besser ist als die Quelle zu iterieren? – bozdoz
@bozdoz: iterating ist besser, da readlines die ganze Datei liest. Nicht gut für große Dateien. Dies setzt natürlich voraus, dass Sie Ihre Modifikationen so lokal ausführen können. Manchmal können Sie nicht, oder Ihr Code wird viel komplizierter. –
Pythons mmap-Modul ermöglicht es Ihnen, in eine Datei einzufügen. Das folgende Beispiel zeigt, wie es unter Unix gemacht werden kann (Windows mmap kann anders sein). Beachten Sie, dass dies nicht alle Fehlerbedingungen behandelt und Sie die ursprüngliche Datei möglicherweise beschädigen oder verlieren. Außerdem werden Unicode-Zeichenfolgen nicht behandelt.
import os
from mmap import mmap
def insert(filename, str, pos):
if len(str) < 1:
# nothing to insert
return
f = open(filename, 'r+')
m = mmap(f.fileno(), os.path.getsize(filename))
origSize = m.size()
# or this could be an error
if 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 mit Dateien ohne mmap zu tun geöffnet in ‚r +‘ Modus, aber es ist weniger bequem und weniger effizient als Sie müßten lesen und speichern vorübergehend den Inhalt der Datei aus dem Einfügeposition zu EOF - was sehr groß sein könnte.
Das fileinput
Modul der Standard-Bibliothek Python wird eine Datei inplace neu schreiben, wenn Sie die Inplace = 1 Parameter verwenden:
import sys
import fileinput
# replace all occurrences of 'sit' with 'SIT' and insert a line after the 5th
for i, line in enumerate(fileinput.input('lorem_ipsum.txt', inplace=1)):
sys.stdout.write(line.replace('sit', 'SIT')) # replace 'sit' and write
if i == 4: sys.stdout.write('\n') # write a blank line after the 5th line
Dies ist IMO die richtige Antwort. –
Wie soll das in python3 funktionieren? Ich habe gerade eine App portiert, die einen solchen Code von Python zu Python3 hatte und ich konnte das gar nicht zum Laufen bringen. Die 'line'-Variable ist ein Bytes-Typ, ich habe versucht, es in Unicode zu decodieren und dann zu modifizieren und dann wieder in Bytes zu kodieren, aber es würde einfach nicht richtig funktionieren. Es hat eine Ausnahme ausgelöst, von der ich mich nicht mehr erinnern kann. Verwenden Leute fileinput inplace = 1 in python3 mit Erfolg? – robru
@Robru: hier ist [Python 3 Code] (http://Stackoverflow.com/a/20593644/4279) – jfs
Wie Adam erwähnt haben Sie Ihre Systemeinschränkungen zu berücksichtigen, bevor Sie entscheiden können, auf Ansatz, ob Sie genug Speicher haben, um alles in den Speicher zu lesen, ersetzen Sie Teile davon und schreiben Sie es neu.
Wenn Sie mit einer kleinen Datei oder haben keine Speicherprobleme könnte dies zu tun hat helfen:
Option 1) Lesen Sie in den Speicher gesamte Datei, auf die gesamte oder einen Teil der Leitung eine regex Substitution tun und ersetze sie mit dieser Zeile plus der zusätzlichen Zeile. Sie müssen sicherstellen, dass die "Mittellinie" in der Datei eindeutig ist, oder wenn Sie Zeitstempel auf jeder Zeile 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) Abbildung Mittellinie, und ersetzen Sie es mit dieser Zeile plus zusätzliche Zeile.
# 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()
Schrieb eine kleine Klasse dafür sauber zu machen.
import tempfile
class FileModifierError(Exception):
pass
class FileModifier(object):
def __init__(self, fname):
self.__write_dict = {}
self.__filename = fname
self.__tempfile = tempfile.TemporaryFile()
with open(fname, 'rb') as fp:
for line in fp:
self.__tempfile.write(line)
self.__tempfile.seek(0)
def write(self, s, line_number = 'END'):
if line_number != 'END' and not isinstance(line_number, (int, float)):
raise FileModifierError("Line number %s is not a valid number" % line_number)
try:
self.__write_dict[line_number].append(s)
except KeyError:
self.__write_dict[line_number] = [s]
def writeline(self, s, line_number = 'END'):
self.write('%s\n' % s, line_number)
def writelines(self, s, line_number = 'END'):
for ln in s:
self.writeline(s, line_number)
def __popline(self, index, fp):
try:
ilines = self.__write_dict.pop(index)
for line in ilines:
fp.write(line)
except KeyError:
pass
def close(self):
self.__exit__(None, None, None)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
with open(self.__filename,'w') as fp:
for index, line in enumerate(self.__tempfile.readlines()):
self.__popline(index, fp)
fp.write(line)
for index in sorted(self.__write_dict):
for line in self.__write_dict[index]:
fp.write(line)
self.__tempfile.close()
Dann können Sie es auf diese Weise verwenden:
with FileModifier(filename) as fp:
fp.writeline("String 1", 0)
fp.writeline("String 2", 20)
fp.writeline("String 3") # To write at the end of the file
http://stackoverflow.com/questions/1325905/inserting-line-at-specified-position-of-a-text-file -in-python/1325927 # 1325927 – pmav99
Sie können sich auf [diese] (http://stackoverflow.com/a/1325927/2276527) Antwort von Alex Martelli beziehen. – Gogo
http://StackOverflow.com/a/4358169/538284 –