bestimmte Zeilen einer ASCII Datei Löschen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Tanja87
User
Beiträge: 1
Registriert: Mittwoch 5. Januar 2011, 11:47

Hallo Leute,

hat jemand zufällig ein Skript zur Hand mit dem ich bestimmte Zeilen einer ASCII Datei löschen kann?
konkret geht es um Folgendes:
ich muss immer wieder ASCII Dateien auslesen bei denen ich nur die Zeilen 30 bis 235 brauche.
davor und Dahinter interessiert mich nicht.
Die Ausgabe sollte in eine andere Datei erfolgen.
Wär echt genial wenn mir da jemand weiterhelfen könnte.

vielen Dank
Gruß
Tanja
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Also so ein Skript kannst du dir doch einfach in <10 Zeilen schreiben, einfach mit ``with``-Statement, ``enumerate``, und Generatoren die deine Bedingung prüfen. Probier doch mal selbst.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Willkommen im Forum!

Weil mir grad langweilig war:

Code: Alles auswählen

from contextlib import nested
def loot(fname, outname):
    with nested(open(fname), open(outname, 'w')) as (in_, out):
        for i, line in enumerate(in_):
            if 29 <= i <=234:
                out.write(line)
            if i > 234:
                break
P.S. Eine "Idee" ist das allerdings nicht ..
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Oder mittels itertools.islice.
Das Leben ist wie ein Tennisball.
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

die Frage ist ob man dies in Python machen muss. Mit 'head' and 'tail' geht es auch. Wahrscheinlich auch mit grep oder sed:

Code: Alles auswählen

C:\>head -n 235 input_datei.txt | tail +30
diese Programme gibt es auch für Windows.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

DaMutz hat geschrieben:diese Programme gibt es auch für Windows.
Muß man aber nachinstallieren. Zum Bsp. hier.
Benutzeravatar
zimmernagel
User
Beiträge: 24
Registriert: Dienstag 9. Dezember 2014, 13:22
Wohnort: Bitburg

Hallo!

Ich habe ein ähnliches Problem, allerdings handelt es sich um eine DGM-XYZ-Ascii-Datei.

Wir benutzen eigentlich Civil 2015, um ein DGM einzulesen, aber die Datei ist 1.2 GByte groß und wir brauchen z.b. nur eine Ortslage, die über ein angegebenes Koordinaten-Rechteck abgebildet werden könnte...

Die Dateigröße ist auch ein Problem, bekomme diese fast nur mit UltraEdit auf, Civil 2015 neigt dazu, sich gerne in's Nirvana zu verabschieden.

Da dort aber z.b. eine ganz Verbandsgemeinde abgebildet ist mit Koordinaten und Höhen z.B.:

308000.000 5526000.000 314.916
308005.000 5526000.000 317.069
308010.000 5526000.000 319.278
308015.000 5526000.000 321.460
308020.000 5526000.000 323.489
308025.000 5526000.000 324.620
308030.000 5526000.000 324.844
308035.000 5526000.000 324.300
308040.000 5526000.000 322.945
308045.000 5526000.000 322.310
308050.000 5526000.000 322.477

Jetzt brauche ich allerdings nur ein Rechteck von
UNTEN-LINKS: 326000 5536000
bis
OBEN-RECHTS: 328000 5538000

Alles andere kann in der Datei gelöscht werden, bzw. das Rechteck könnte in eine andere Datei gespeichert werden...

Mit AutoCAD Visual Lisp hatte ich das auch probiert (allerdings steigt das nackte Autocad auch schon irgendwann aus, wegen der Größe der Datei!)

Leider bin ich ganz und gar nicht fit mit Python, allerdings sah das Thema hier ziemlich passend für mich aus...

Vielen Dank für die vielen Tipps und Bemühungen! :-)

SG,
Arwed Fränken
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Der Sachverhalt ist zwar gut beschrieben, es fehlt aber ein entscheidender Teil: Was genau ist das Problem? Wie sieht dein jetziger Ansatz aus?
Das Leben ist wie ein Tennisball.
Benutzeravatar
zimmernagel
User
Beiträge: 24
Registriert: Dienstag 9. Dezember 2014, 13:22
Wohnort: Bitburg

Das Problem ist eigentlich ganz einfach:

a) Ich kenn mich in Autocad visual lisp ganz gut aus..., komme aber da wegen der Größe der Datei nicht weiter...
b) in Python bin ich noch nackter wie ein blutiger Anfänger... - lade mir grad mal python runter...
c) die Überschrift vom Thema war ideal für mich...
d) ich muss mich erstmal in python reinlesen, um da was selbst auf die Beine zu stellen...
e) Ist Python überhaupt dafür geeignet so eine große Datei zeilenweise zu bearbeiten?

Sg,
Arwed
BlackJack

@zimmernagel: e) Ja da ist Python geeignet. Aber eigentlich auch jede andere Programmiersprache. Mir ist keine Programmiersprache bekannt in der man nicht Dateien zeilenweise lesen/schreiben kann, und Zeichenkettendarstellungen von Gleitkommazahlen in Gleitkommazahlen umwandeln und mit vorgegebenen Werten vergleichen kann, die die Bezeichnung Programmiersprache verdient hätte.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ja, das ist mögliche. Arbeite erstmal das Tutorial aus der Dokumentation durch, dann hast du eigentlich das nötige Handwerkszeug zusammen.

Was soll denn genau mit den Daten gemacht werden? Sollen über alle Zeilen das Minimum und das Maximum der ersten und der zweiten Spalte bestimmt werden? Das braucht ja nur ein paar Zeilen (ungetestet):

Code: Alles auswählen

with open("data.dat") as fp:
    iterator = (map(float, line.split()[:2]) for line in fp)
    x_min, y_min = x_max, y_max = next(iterator)

    for x, y in iterator:
        x_min, x_max = min(x_min, x), max(x_max, x)
        y_min, y_max = min(y_min, y), max(y_max, y)
    
    print x_min, x_max
    print y_min, y_max
Das Leben ist wie ein Tennisball.
Benutzeravatar
zimmernagel
User
Beiträge: 24
Registriert: Dienstag 9. Dezember 2014, 13:22
Wohnort: Bitburg

Hallo EyDu!

Ja, es sollen alle Zeilen der Datei durchforstet werden, ob die Koordinate in dem Rechteckbereich liegt, dann sollte diese entweder in eine neue Datei eingesetzt werden, sodaß nach und nach eine Datei entsteht die genau nur dieses vordefinierte Rechteck als Koordinaten beherbergt.

Oder man holt die Original-Datei und löscht alle Zeilen heraus, die ausserhalb des definieten Rechteckes liegen.

Gibt es da eine Möglichkeit, die Koordinaten von "unten-links" und "oben-rechts" dann einzugeben?

Am besten soll eine neue AScii-Datei erstellt werden, die dann zeilenweise gefüllt wird...

Muss heute abend mal python installieren, hier auf dem pc kann ich keine *.msi-Dateien installieren. *nerv*
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Und ich wollte cofi schon fragen, wieso er solch deprecated Code hier postest:

Code: Alles auswählen

with nested(open(fname), open(outname, 'w')) as (in_, out):
... dann sah ich das Datum des Threads :twisted:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
zimmernagel
User
Beiträge: 24
Registriert: Dienstag 9. Dezember 2014, 13:22
Wohnort: Bitburg

Ohje, das ist ja schon viel Leserei, bis man(n) mal so langsam "Plan" bekommt, wie das in Python ablaufen könnte...
Hat da nicht jemand schon sowas ähnliches gebastelt - als Pfad, wie das ungefähr auszusehen hätte?

Ich will also folgendes:
a) Die Dateien sollten am besten mit Tinker angeklickt werden (Fensterauswahl) ... bei Zieldatei müsste ich eine neuen anlegen können...
a) Ich will die Datei "DGM.xyz" in Laufwerk C:\ unter C:\TEMP öffnen.
b) Die Ausgabedatei soll auch unter C:\TEMP\ abgelegt werden mit einem vorher abgefragten Namen und Endung wieder .xyz.
c) Jetzt müsste ich ein Koordinatenfenster eingeben können mit 4 Feldern (Punkt Unten-Links und Punkt Oben-Rechts)
Feld1:UL-Koordinate-X, Feld2:UL-Koordnate-Y, Feld3: OR-Koordinate-X, Feld 4: OR-Koordinate-Y
d) Jetzt sollte alles in der Originaldatei DGM.xyz zeilenweise durchgesucht werden, ob die einzelnen Zeilen ausserhalb oder innerhalb dieses Rechteckes drin sind...
e) wenn sie ausserhalb sind, soll zur nächsten Zeile in der Original-Datei gesprungen werden.
f) wenn sie INNERHALB sind, soll diese Zeile einfach in die Zieldatei reingeschrieben werden.
g) Das soll solange weiterlaufen, wie die Originaldatei Zeilen hat...
h) Frage: Die Original-Datei hat 1.2 GByte, ist das ein Problem, bzw. wie lange könnte das dauern? (die Datei hat 38.412.401 Zeilen...!!!)
i) Der Aufbau der Zeilen ist ziemlich einfach gestrickt (Auszug!):
308000.000 5526000.000 314.916
308005.000 5526000.000 317.069
308010.000 5526000.000 319.278
308015.000 5526000.000 321.460
308020.000 5526000.000 323.489
308025.000 5526000.000 324.620
308030.000 5526000.000 324.844
308035.000 5526000.000 324.300
308040.000 5526000.000 322.945
308045.000 5526000.000 322.310
308050.000 5526000.000 322.477
308055.000 5526000.000 323.343
308060.000 5526000.000 325.671
308065.000 5526000.000 327.699
308070.000 5526000.000 329.634
308075.000 5526000.000 331.020
308080.000 5526000.000 334.938
308085.000 5526000.000 338.611
308090.000 5526000.000 336.405
308095.000 5526000.000 331.834
308100.000 5526000.000 329.394
308105.000 5526000.000 326.165
308110.000 5526000.000 324.939
308115.000 5526000.000 324.695
308120.000 5526000.000 325.860
308125.000 5526000.000 328.211
j) Das sind einfache Koordinaten, x-y-z.
BlackJack

@zimmernagel: a1) Da gibt es schon fertige Dialoge für. Such mal über den Index in der Python-Dokumentation nach `askopenfilename()`.

a2) bis c) Das würde man üblicherweise in *einem* Dialog abfragen, also zwei Felder für die Dateinamen/-pfade und jeweils eine Schaltfläche für den Dateidialog, und Eingabefelder für die Koordinaten. Dann eine Schaltfläche um die Verarbeitung zu starten. Dabei werden vorher die Eingaben überprüft (vollständig/sinnvoll/…).

d) bis g) kann man in einer Filterfunktion abhandeln, oder sogar nur in einer Funktion die *eine* Zeile überprüft und die dann zum Beispiel mit `itertools.ifilter()` verwenden.

h) Bei zeilenweiser Verarbeitung ist die Dateigrösse nahezu egal, es muss ja maximal eine Zeile im Arbeitsspeicher sein. Die Verarbeitungszeit dürfte im wesentlichen durch die Geschwindigkeit begrenzt sein in der die Daten vom Hintergrundspeicher gelesen/geschrieben werden können.

Problematisch könnte die Rückmeldung während der Verarbeitung sein. Solange die Funktion läuft, reagiert die GUI nicht, es sei denn man startet die Funktion in einem separaten Thread. Dann müsste man aber die beiden irgendwie koordinieren damit man in der GUI mitbekommt wenn die Verarbeitung abgeschlossen ist. Und vielleicht möchte man ja auch laufend Statusinformation darstellen. *Das* erscheint mir eigentlich das komplizierteste an der ganzen Sache.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@zimmernagel: die Größe der Datei ist nebensächlich, und die Geschwindigkeit hauptsächlich abhängig von der Geschwindigkeit Deiner Festplatte.
Das könnte ungefähr so aussehen:

Code: Alles auswählen

with open(input_filename) as points_in:
    with open(output_filename, 'w') as points_out:
        for line in points_in:
            point = map(float, line.split())
            if left_border <= point[0] <= right_border and top_border <= point[1] <= bottom_border:
                points_out.write(line)
Benutzeravatar
zimmernagel
User
Beiträge: 24
Registriert: Dienstag 9. Dezember 2014, 13:22
Wohnort: Bitburg

Ja, ok, fein, danke! Das ist die Hauptaufgabe des Programmes!

Das ist schon die halbe Miete. Ich hab' jetzt noch mit "file split" die Dateien auf 64mb aufgesplittet bekommen, damit man beim testen nicht so lange warten müsste...

...aber wie sage ich jetzt dem programm, wo die Datei steht, bzw. wo er hinschreiben will? Ich weiss, das ist Standardkram, aber ich hab erst von python erfahren, wo ich mal "Finale" - Musikprogramm installiert habe... - oder war's capella? ;-)

Ich muss dem Programm sagen (z.b. im Format 326000,5536000 (unten-links) und 328000,5538000 (für oben links)) was er als Begrenzung holt für "point[0]" und "point[1]"

Mir würde ja schon reichen, wenn ich das im programm ändern kann...

Fragen über Fragen, als Newbie einer völlig fremden "Sache" ist man erstmal "aufgeschmissen" - erst bei einem praktischen Vorentwurf, dass in die gleiche Richtung des eigenen Problems geht, hat man die magischen "Aha-Erlebnisse"

Vielen Dank für das "Hauptprogramm" :-)
Benutzeravatar
zimmernagel
User
Beiträge: 24
Registriert: Dienstag 9. Dezember 2014, 13:22
Wohnort: Bitburg

Ok, habe das jetzt schonmal bisschen geändert:

Code: Alles auswählen

input_filename='c:\DGM\BitLand\DGMSPLIT\s.0'
output_filename='c:\DGM\BitLand\Output.xyz'
    with open(input_filename) as points_in:
        with open(output_filename, 'w') as points_out:
            for line in points_in:
                point = map(float, line.split())
                if left_border <= point[0] <= right_border and top_border <= point[1] <= bottom_border:
                    points_out.write(line)
Jetzt hängt er aber bei "with open...." mit der Fehlermeldung "unexpected indent"....!?!!?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Die Fehlermeldung sagt es ja schon: Unerwartete Einrückung. In Python ist die Einrückung Teil der Syntax, da darfst du nicht einfach so einrücken. In deinem Fall ist das Problem die Zeile 3, da darf keine Einrückung stehen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
zimmernagel
User
Beiträge: 24
Registriert: Dienstag 9. Dezember 2014, 13:22
Wohnort: Bitburg

Das Leben ist wie ein Tennisball, mal auf mal ab..., joo, stimmt! ;-)

Ok, linker Rand mal "optimiert", jetzt kommt natürlich die Fehlermeldung mit dem "linken-Rand"...

Wie muss ich diese Gruppe eingeben, bzw. die Koordinaten?

Unten links, soll z.b. X=326000, Y=5536000 sein, oben links X=328000, Y=5538000 sein...

Code: Alles auswählen

left_border=326000,5536000
???
Antworten