Riesige Text Dateien

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.
Antworten
spinneratz
User
Beiträge: 23
Registriert: Freitag 31. Oktober 2008, 15:41

Hallo,
ich habe eine riesige Text Datei in der Dreiecke und ihre Punkte aufgelistet sind.
Z.B.:
1 3 5 6 (1. Dreieck mit Punkt 3, 5 und 6)
2 4 6 7
3 6 7 8
...
weiter unten kommt die Liste mit den Punkten und ihren Koordinaten:
3 33.55 22.44 5.4
5 22.44 66.77 7.3
6 11.77 66.88 1.5
...

Jetzt soll das umsortiert werden in eine Datei wo die Dreiecksnummer steht und dann gleich die Koordinaten also:
1
33.55 22.44 5.4
22.44 66.77 7.3
11.77 66.88 1.5
...

Hoffe ich hab mich nicht zu konfus ausgedrückt.
Ich kann ja einfach die erste Datei mit xreadlines durchlesen und alles in Listen packen, dann umsortieren und wieder in eine andere Datei schreieben.
Problematisch wird das aber wahrscheinlich weil die erste Datei rund 26 MB groß ist.
Was meint Ihr geht das mit Listen, oder gibt es da was effektiveres?
Z.B. sowas wie: Wenn Dreieckszeile, dann suche nach den Punkten weiter unten uns schreibe sie raus.
Ich muss allerdings noch sagen, dass meine Pythonkenntnisse nicht sehr weit gehen. Deswegen wärs nett wenn jemand was mit Beispielen posten könnte.
Danke schonmal!
BlackJack

Woran erkennst Du denn wo die Dreiecke aufhören und die Koordinaten beginnen?

26 MiB ist heutzutage nun auch nicht mehr sooo viel. Ich würde erst einmal schauen, ob ganz naives, komplettes Einlesen funktioniert und erst bei Problemen komplizierteren Code schreiben.

Da wäre der erste Schritt dann Dreiecke überlesen, Koordinaten komplett lesen, Datei neu öffnen und die Dreiecke zeilenweise verarbeiten.

Falls Du am Ausgabeformat noch etwas drehen kannst, würde ich vorschlagen ein komplettes Dreieck pro Zeile zu speichern. Sonst macht man sich die Weiterverarbeitung unnötig schwerer.

Warum soll eigentlich umsortiert werden? Zumindest wenn es sich um grösstenteils zusammenhängende "meshes" handelt, dürften die Dateien erheblich grösser werden, weil alle geteilten Punkte jetzt pro beteiligtem Dreieck einen eigenen "Datensatz" bekommen.
spinneratz
User
Beiträge: 23
Registriert: Freitag 31. Oktober 2008, 15:41

Die Daten sollen umgeschrieben werden weil die Daten von einem Programm an ein anderes übergeben werden sollen, das nur dieses Format so wie von mir beschrieben lesen kann.
Ich habe schon mal was ähnliches mit größeren Dateien gemacht und habe mich damals auch schon gefragt ob das nicht besser ginge als alles in Listen zu lesen. Könnte mir vorstellen, das das den Speicher ganz schön aufbläht. Aber ist nur eine Vermutung.
Hat noch jemand Ideen, wie man anhand meines Beispiels in Textdateien "Datenabankähnlich" suchen könnte?
:roll:
tordmor
User
Beiträge: 100
Registriert: Donnerstag 20. November 2008, 10:29
Wohnort: Stuttgart

spinneratz hat geschrieben: Hat noch jemand Ideen, wie man anhand meines Beispiels in Textdateien "Datenabankähnlich" suchen könnte?
:roll:
In dem man die Punkte in eine Datenbank schreibt. Ggf. sqlite.
BlackJack

@spinneratz: Wenn Du wirklich alles aus der Datei in Listen stecken würdest, solltest Du noch einmal das Tutorial aus der Python-Dokumentation durcharbeiten. Es gibt noch mehr Datentypen in den "built ins" als Listen.
spinneratz
User
Beiträge: 23
Registriert: Freitag 31. Oktober 2008, 15:41

Ich möchte allerdings nicht extra eine Datenbank aufsetzen...
BlackJack

@spinneratz: Ich würde eine Datenbank hier auch als "Overkill" sehen, aber Datenbank heisst ja nicht rieseiger, externer DBMS-Server-Prozess. `anydbm`, `shelve`, `sqlite` sind alles Datenbanken und da braucht man nichts aufsetzen.
spinneratz
User
Beiträge: 23
Registriert: Freitag 31. Oktober 2008, 15:41

Habe mir schon die anderen Datentypen angesehen. Aber ich das Problem dass man während dem lesen einer Zeile gleich weiter unten in der Datei nach den Punktzahlen sucht wird damit glaube ich nicht gelöst.
Wenn man alles einliest und in Listen speichert, welche Datenstruktur würde denn hier Vorteile bringen? Dictionaries? Weiß nicht...?
Außerdem fehlt es mir ehrlich an Erfahrung welche Listentypen hier geeignet sind.
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

Hier ein Vorschlag.

Annahme: Dreiecksecken lassen sich mit int() umwandeln.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from StringIO import StringIO
from pprint import pprint

data = """1 3 5 6
2 4 6 7
3 6 7 8
3 33.55 22.44 5.4
5 22.44 66.77 7.3
6 11.77 66.88 1.5
4 1.0 2.0 3.0
7 10.0 11.0 12.0
8 20.0 30.0 40.0"""

class Punkt(object):
    def __init__(self, id, x=None, y=None, z=None):
        self.id, self.x, self.y, self.z = id, x, y, z

    def __repr__(self):
        return "<Punkt %i: %f, %f, %f>" % (self.id, self.x, self.y, self.z)

class Dreieck(object):
    def __init__(self, id, x, y, z):
        self.id, self.x, self.y, self.z = id, x, y, z

    def __repr__(self):
        return "<Dreieck %i: %r, %r, %r>" % (self.id, self.x, self.y, self.z)

punkte = {}
dreiecke = {}

for line in StringIO(data):
    id, x, y, z = line.split()
    id = int(id)
    try:
        # Dreieck
        ix, iy, iz = int(x), int(y), int(z)
        dreiecke[id] = Dreieck(id,
                               punkte.setdefault(ix, Punkt(ix)),
                               punkte.setdefault(iy, Punkt(iy)),
                               punkte.setdefault(iz, Punkt(iz)))
    except:
        # Punkt
        fx, fy, fz = float(x), float(y), float(z)
        punkte[id] = Punkt(id, fx, fy, fz)

for dreieck in dreiecke.values():
    dreieck.x = punkte[dreieck.x.id]
    dreieck.y = punkte[dreieck.y.id]
    dreieck.z = punkte[dreieck.z.id]

pprint(dreiecke)
Ausgabe:

Code: Alles auswählen

% python dreieck.py
{1: <Dreieck 1: <Punkt 3: 33.550000, 22.440000, 5.400000>, <Punkt 5: 22.440000, 66.770000, 7.300000>, <Punkt 6: 11.770000, 66.880000, 1.500000>>,
 2: <Dreieck 2: <Punkt 4: 1.000000, 2.000000, 3.000000>, <Punkt 6: 11.770000, 66.880000, 1.500000>, <Punkt 7: 10.000000, 11.000000, 12.000000>>,
 3: <Dreieck 3: <Punkt 6: 11.770000, 66.880000, 1.500000>, <Punkt 7: 10.000000, 11.000000, 12.000000>, <Punkt 8: 20.000000, 30.000000, 40.000000>>}
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Moin,

nicht schön, aber selten:

Code: Alles auswählen

index = dict()

with open("test.txt") as data:
    # first index all coordinates
    # skip triangle defs
    while data.readline().strip():
        pass
    # collect index coordinates
    line = data.readline()
    while line:
        point = line.split()[0]
        index[point] = data.tell() - len(line)
        line = data.readline()
    # back to begin of file
    data.seek(0)
    # write new file
    with open("new.txt", "w") as new_data:
        # go through all triangles and get coords using index
        while True:
            triangle_def = data.readline().strip().split()
            current_pos = data.tell()
            if not triangle_def:
                break
            # collect data
            triangle_data = list()
            triangle_data.append(triangle_def[0] + "\n")
            for point in triangle_def[1:4]:
                # jump to point definition
                pos = index[point]
                data.seek(pos)
                coords = data.readline().rstrip().split()
                coords = ' '.join(coords[1:])
                # write coords
                triangle_data.append(coords + "\n")
            new_data.writelines(triangle_data)
            # back to next triangle def
            data.seek(current_pos)
Zuerst werden die Positionen aller Punkte in einem Index gespeichert. Danach wird die Datei wieder von vorn durchlaufen und alle Dreiecke im neuen Format gespeichert. Da im ersten Durchlauf die Punkte indiziert wurden, kann man diese Punkte direkt anspringen, lesen und verarbeiten.

Ich nehme hier einfach mal an, dass die Dreiecksdefinitionen von den Punktdefinitionen mit einer Leerzeile getrennt sind.

Gruß,
Manuel
spinneratz
User
Beiträge: 23
Registriert: Freitag 31. Oktober 2008, 15:41

Hey cool. Muss mir die Codes mal in Ruhe durchdenken...
Nachtrag: Vor den Dreiecken steht ein DR
und bei den Punkten ein P somit hat man Key Wörter um zu ckecken ob ein Dreicke oder Punkt losgeht
Antworten