2016-05-13 15 views
-1

Ich habe versucht, eine Möglichkeit zu denken, wie folgt zu tun:Python Schreiben von Zeilen aus der Liste verursacht IndexError

Eine Datei wird geöffnet und gelesen. Die Datei enthält die folgenden

15;0 
2;0 

die Zeilen zu lesen, wobei die erste Ziffer der Linie ersetzt die zweiten und die erste Ziffer der Leitung von 0 ersetzt:

f = open("data.txt", "r+") 

for line in f: 
    if line != "\n": 
     lineList = line.replace("\n", "").split(";") 
     lineList[1] = lineList[0] 
     lineList[0] = "0" 
     dataLine = lineList[0] + ";" + lineList[1] 
     f.write(dataLine) 

f.close() 

Das Problem tritt auf, wenn Schreiben der Zeile in Datei. Wie kann ich beide Zeilen am Ende der Datei schreiben und die ersten beiden Zeilen löschen? Danke

+0

Bitte die Traceback-Nachricht anzeigen. –

+0

IndexError: Listenindex außerhalb des zulässigen Bereichs. Die Textdatei wird mit diesem http://imgur.com/xtddcJf – Johny

+2

gefüllt. Bitte bearbeiten Sie Ihren Beitrag, um die gesamte Traceback-Nachricht einzuschließen, da ich sehr bezweifle, dass 'f.write (..)' einen IndexError auslösen wird. –

Antwort

3

Der schnellste Weg zur Implementierung der Lösung (und wahrscheinlich eine logisch korrekte Art) besteht darin, zuerst den Inhalt der Datei in einem Kontextmanager zu lesen und anschließend die verarbeiteten Daten in dieselbe Datei innerhalb eines anderen Kontextmanagers zu schreiben:

data = list() 
with open("data.txt", "r") as f: 
    for line in f.readlines(): 
     if line != '\n': 
      listLine = line.split(";") 
      data.append("0;{}\n".format(listLine[0])) 

with open('data.txt', 'w') as f: 
    for line in data: 
     f.write(line) 

auch brauchen Sie nicht den Aufwand für verschiedene Werte listLine Liste zuweisen und dann eine Dateneingabe zu schaffen in der Datei zu schreiben. Verwenden Sie einfach geradeaus, was Sie bereits haben.

Der Nachteil dieser Methode ist die Speichernutzung - wenn Ihre Datei größer als Ihr Speicher ist, benötigen Sie einen anderen Ansatz.

+0

Das hat den Trick gemacht. Vielen Dank – Johny

1

Überprüfen Sie Ihren Code.

listLine = line.split(";") 
lineList[1] = lineList[0] 
lineList[0] = "0" 

Sie legen die Variable listLine fest und rufen dann lineList auf.

+1

Fehler bei der Vereinfachung des Codefragments. Danke, dass Sie darauf hingewiesen haben – Johny

0

Die Lösung von @iulian ist eine gute, aber wie er gewarnt hatte - es benötigt genügend Speicher, um die Daten zu halten. Wenn Sie große Dateien erwarten und akzeptieren können vorübergehend zusätzlichen Speicherplatz verwenden (anstelle von RAM), Sie in eine separate Ausgabedatei schreiben kann, verarbeiteten Daten schreiben, dann das Original mit ersetzen:

import shutil 
import tempfile 

with open("data.txt", "rU") as f_in: 
    f_out = tempfile.NamedTemporaryFile(delete=False) 
    for line in f_in: 
     if ";" in line: 
      line = "0;{}\n".format(line.split(";", 1)[0]) 
     f_out.write(line) 
    f_out.close() 
    shutil.move(f_out.name, "data.txt") 

Sie können‘ t Ersetzen Sie Daten vor Ort, wenn Sie nicht garantieren können, dass neue Zeilen nicht länger als alte Zeilen sind. Wenn dies geschieht, werden Sie sich selbst in einer Situation begegnen, in der Ihre Schreibposition weiter ist als eine, und die Datei wird beschädigt.

Wenn Sie jedoch sicher sein, dass keine neue Zeile länger sein wird als ein altes (zB gibt es definitiv keine "1234;" Linien in Quelle, die "0;1234" nach der Transformation werden würde), können Sie dies auch tun:

with open("data.txt", "rb+") as f: 
    write_offset = 0 
    for line in f.readlines(): 
     line_len = new_len = len(line) 
     if ";" in line: 
      line = "0;{}\n".format(line.split(";", 1)[0]) 
      new_len = len(line) 
      if new_len > line_len: 
       # Bad things had just happened. 
       raise RuntimeError("New line is longer than old one!" 
            " File is now corrupt.") 

     read_offset = f.tell()   # Remember the current position 
     f.seek(write_offset)    # Seek to where we should write to 
     f.write(line) 
     write_offset += new_len 
     f.seek(read_offset)    # Return to where we were 

    # It could happen that new file is shorter. 
    f.seek(write_offset) 
    f.truncate() 

Diese Version führt die Aktualisierungen direkt durch und benötigt keine zusätzlichen Speicher- oder Festplattenanforderungen.

(Beachten Sie, hat f.readlines() einen Puffer, so f.tell() Ergebnisse werden nicht einzelne Linienverschiebungen sein -. Für den Fall, würden Sie wollen, diejenigen aus irgendeinem Grunde verwenden wir für unsere Zwecke das hier ignorieren.)