Ich verwende 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?
Ich verwende 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?
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.
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
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 der with
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 das inline=True
Argument verwenden. Beispiel hier: stackoverflow.com/a/2363893/47390
f.Close()
Das fileinput
Modul 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 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
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()
Stattdessen shutil
können Sie Folgendes verwenden.
import os
os.rename( aFile, aFile+"~" )
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.
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 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()
Schrieb eine kleine Klasse dafür sauber.
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 folgendermaßen 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
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:
$ cat my_data.txt
This is a data file
with all of my data in it.
Dann können Sie mit dem os
Modul die üblichen sed
Befehle verwenden
import os
# Identifiers used are:
my_data_file = "my_data.txt"
command = "sed -i 's/all/none/' my_data.txt"
# Execute the command
os.system(command)
Wenn Sie sich sed nicht bewusst sind, probieren Sie es aus, es ist äußerst nützlich.