it-swarm.com.de

Wie ändere ich eine Textdatei?

Ich verwende Python und möchte einen String in eine Textdatei einfügen, ohne die Datei zu löschen oder zu kopieren. Wie kann ich das machen?

159
Oscar

Leider gibt es keine Möglichkeit, eine Datei in die Mitte 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 der Funktion "Suchen" überschreiben. Wenn Sie jedoch am Anfang oder in der Mitte etwas hinzufügen möchten, müssen Sie es neu schreiben.

Dies ist eine Betriebssystemsache, keine Python) Sache. Sie ist in allen Sprachen gleich.

Normalerweise lese ich aus der Datei, nehme die Änderungen vor und schreibe sie in eine neue Datei mit dem Namen myfile.txt.tmp oder so ähnlich. Dies ist besser als das Einlesen der gesamten Datei in den Speicher, da die Datei dafür möglicherweise zu groß ist. Sobald die temporäre Datei fertig ist, benenne ich sie genauso um wie die ursprüngliche Datei.

Dies ist eine gute und sichere Methode, denn wenn der Schreibvorgang der Datei aus irgendeinem Grund abbricht oder abstürzt, haben Sie immer noch Ihre unberührte Originaldatei.

131
Adam Pierce

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 vortäuschen 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
94
Armin Ronacher

Das fileinput -Modul der Python Standardbibliothek schreibt a neu Datei an Ort und Stelle, wenn Sie den Parameter an Ort und Stelle = 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
66
Dave

Das Umschreiben einer Datei erfolgt häufig durch Speichern der alten Kopie unter einem geänderten Namen. Unix-Leute fügen ein ~ um den alten zu markieren. Windows-Benutzer erledigen alle möglichen Aufgaben - fügen Sie .bak oder .old hinzu - oder benennen Sie die Datei vollständig um oder setzen Sie das ~ vor den Namen.

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()

Anstelle von shutil können Sie Folgendes verwenden.

import os
os.rename( aFile, aFile+"~" )
31
S.Lott

Mit dem mmap-Modul von Python können Sie Daten in eine Datei einfügen. Das folgende Beispiel zeigt, wie dies unter Unix gemacht 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. Außerdem werden Unicode-Zeichenfolgen nicht verarbeitet.

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()

Dies ist auch ohne mmap mit Dateien möglich, die im Modus 'r +' geöffnet wurden. Dies ist jedoch weniger bequem und effizient, da Sie den Inhalt der Datei von der Einfügeposition in EOF - das könnte riesig sein.

14
mhawke

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 zu lesen. Ersetzen Sie Teile davon und schreiben Sie es erneut.

Wenn Sie mit einer kleinen Datei arbeiten oder keine Speicherprobleme haben, kann dies helfen:

Option 1) Liest die gesamte Datei in den Speicher, ersetzt die gesamte oder einen Teil der Zeile durch einen regulären Ausdruck und ersetzt sie durch diese Zeile plus der zusätzlichen Zeile. Sie müssen sicherstellen, dass die 'mittlere Zeile' in der Datei eindeutig ist, oder 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) Finde die mittlere Linie heraus und ersetze sie durch diese Linie plus der zusätzlichen 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()
13
Maxime R.

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 so benutzen:

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
1
ananth krishnan

Wenn Sie Unix kennen, können Sie Folgendes versuchen:

Anmerkungen: $ bedeutet die Eingabeaufforderung

Angenommen, Sie haben eine Datei my_data.txt mit folgendem Inhalt:

$ cat my_data.txt
This is a data file
with all of my data in it.

Mit dem Modul os können Sie dann 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 sed nicht kennen, probieren Sie es aus, es ist äußerst nützlich.

0
G. LC