Dateioperationen -- Anzahl der Zeilen

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
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

ich hab mal wieder ein Problem. Ich hab eine sehr lange Datei, von der ich nicht weiß, wieviele Zeile sie hat. Da ich das aber brauche hab ich mir mal folgenden Algorithmus gebastelt:

Code: Alles auswählen

f=open(filename,'r')
lines=0L
for line in f.xreadlines():
    lines+=1L
f.close()
Die Frage ist nun, ob es nicht eine schnellere Variante gibt. mit tell und seek kann man ja die Zeilenposition bestimmen, aber leider nur byteweise. Gib es nich auch eine Methode dafür? Oder ist das wirklich die schnellste Variante, die es dafür gibt?
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

mal eine dumme nebenfrage: was soll das "L" hinter den Zahlen?
mfg,

10011110
RicmanX
User
Beiträge: 69
Registriert: Donnerstag 29. August 2002, 17:10
Wohnort: Erfurt
Kontaktdaten:

Das L steht für LongInteger, d.h. für Zahlen die verdammt groß sind und sonst nicht in den Speicher passen würden.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Auf die Gefahr hin dass ich mich unbeliebt mache: Unter Linux / Unix würde ich einen Rückgriff auf das Systemkommando wc machen.

Code: Alles auswählen

wc -l Dateiname # gibt Anzahl der Zeilen
wc -l Dateiname* # gibt Dateinamen und Anzahl der Zeilen
Schneller bekomme ich das mit keiner anderen Routine hin.

Ich weiß nicht ob es bei Windows eine API - Funktion dafür gibt. Und MAC?

Hans
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

ich möcht nicht unbedingt Treaths oder externe Programme nutzen, da das unabhängig sein soll und sich was äußeres ja immer ändern kann. aber auch wenn, wüsste ich weder für win noch für mac ein passendes Programm. das ist ja mein Problem... :?
Beyond
User
Beiträge: 227
Registriert: Freitag 6. September 2002, 19:06
Kontaktdaten:

Ich denke die xreadlines-Variante ist schon aüßerst schnell, da xreadlines in C programmiert ist. In Python selbst bekommst Du vmtl. nichts schnelleres und es bleibt auch nichts überig außer die Datei Byte für Byte zu lesen. Man weiß ja nicht wo Zeilenumbrüche sind. Schneller wäre es wenn Du die Länge der einzelnen Zeilen kennst oder Dich mit einer Schätzung zufrieden gibst.
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

nö... muss es genau wissen. aber wenns nichts schnelleres gibt kann ich damit leben. thx.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Probieren geht über studieren. Mein Wald und Wiesen PC bringts bei ca. 2,5 Millionen Datensätzen (ca. 175 MB) immerhin auf 30 Sekunden. Ein vernünftiger Server sollte das eigentlich unter 10 Sekunden schaffen.

wc -l scheint auch nicht wesentlich schneller zu arbeiten.

Hans
Beyond
User
Beiträge: 227
Registriert: Freitag 6. September 2002, 19:06
Kontaktdaten:

Klar, weil xreadlines in C programmiert ist und das ganze Python-Programm ja nicht sehr viel mehr macht. Schließlich muß die gesammte Datei gelesen werden, da bremst die Festplatte wohl.

Erstaunlich schnell ist tar. Den Quellcode wollte ich mir mal ansehen.

cu beyond
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

habe zwar keine c Kenntnisse, aber vermutlich liest tar einen kompletten Block (Sektor?) von der Platte und hängt ihn so an die Datei an ohne diesen zu analysieren. Wenn du Texte liest, kannst du das doch nur Zeichen für Zeichen machen bis ein Zeilenende kommt. funktionen die ein ganze Zeile lesen sind m. E. doch nur abgeleitet um zu vereinfachen.

Hans
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo,

das Geheimnis ist ein buffer, hier mal das Prinzip:

Code: Alles auswählen

reserviere 100000 Bytes für den buffer
setze Zeilenzähler auf 0
öffne Datei
solange noch nicht EOF erreicht ist:
    lese 100000 Bytes aus Datei in den buffer
    zähle alle Zeilenumbrüche im buffer
    erhöhe Zeilenzähler um die gezählten Zeilen
schließe Datei
das macht wc so schnell, egal obs in C oder Pascal oder sonstwas programmiert wäre. Natürlich müsste mann bei einem richtigen Programm noch abfragen, ob auch 100000 Bytes gelesen wurden um nicht über das Ende hinaus Zeilenumbrüche zu lesen.


Gruß

Dookie
Beyond
User
Beiträge: 227
Registriert: Freitag 6. September 2002, 19:06
Kontaktdaten:

wc ist ja eben nicht besonders schnell. Aber tar. Ein Buffer gehört dazu, das geht mit Python aber auch problemlos

Code: Alles auswählen

bla= file.read(bufSize)
Das für Python in C implementierte xreadlines wird das auch so machen. Schließlich muß aber noch den Buffer nach "newlines" durchsehen.

Für ein tar-Kopieren ist dies nicht erforderlich. Ich habe mir überlegt ob es bei besseren OS Linux/Unix/BSD etc. einen Befehl gibt "Kopiere Daten von Device A nach Device B". Macht hinsichtlich eines möglichen SCSI-Controllers äußerst viel Sinn und würde auch die Geschwindigkeit von tar erkären. Denn entweder das Betriebssystem erledigt das Kopieren der Daten oder sogar ein eigener Prozessor/Controller.

cu beyond
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Beyond hat geschrieben:Ich habe mir überlegt ob es bei besseren OS Linux/Unix/BSD etc. einen Befehl gibt "Kopiere Daten von Device A nach Device B".
:?::?::?: Du gibst zu, mit einem "minderwertigem" OS zu arbeiten :?::?::?: :D
Bitte keinen Flame starten :!:

Also Linux / UNIX kennt eigentlich nicht viel von Hardware. Man spricht alles nur als Datei an. Ein Beispiel mit tar

Code: Alles auswählen

# sichert mein Homverzeichnis nach /tmp/hans.tar
tar cvf /tmp/hans.tar  /home/hans
# sichert mein Homeverzeichnis auf DAT
tar cvf /dev/rct0 /home/hans 
die Gerätedatei (/dev/rct0) kann allerdings von System zu System unterschiedlich benannt sein.

Hans
Beyond
User
Beiträge: 227
Registriert: Freitag 6. September 2002, 19:06
Kontaktdaten:

Nein.

"Mit Linux wär das auch passiet"

"Internet Explorer ist der Standard und das ist gut so"

:D :D :D :D Einige beliebte Sprüche aus den Heise-Forum :D :D :D :D

Ich verwende hauptsächlich Linux, aber ich habe mich bisher nicht mit Kernel-Programmierung auseinander gesetzt, daher weiß ich nicht ob es entsprechende Befehle gibt.

Alle OS (sogar Windows) können etwas mit Busmaster-Karten etc. anfangen. Dann geht das lesen/schreiben halbwegs schnell, weil die Sachen von alleine im Arbeitspeicher landen/von dort gelesen werden. Richtig schnell wäre aber, die Daten nicht erst in den Arbeitsspeicher zu laden und dann wieder von dort wegzukopieren, sondern eben direkt von Gerät A nach Gerät B. Eine solche Unterstützung müßte dann in den entsprechenden Treibern (Kernel oder Module) implementiert sein.

Als Benutzer kriegt man von alle dem natürlich nichts mit. Man sagt einfach zu Device xy kopieren. Wie das intern geschieht, weiß man nicht und muß es auch nicht wissen. Das ist wie bei einem RAID. Da sieht man normalerweise auch nur eine "Platte". Man kann aber auch den RAID als physische Devices betrachten, wenn man weiß wie die entsprechenden Devices heißen. Das ist aber meist nicht Zeil der Sache (außer man will einen größeren Datenschaden reparieren :cry:)

Frohe Weihnachten,
beyond
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Sorry wolte die nicht zu nahe treten, aber besseres Betriebsystem wie hattest du geschrieben. Ich fand das soooo einladend. :D

Ich habe aber jetzt verstanden was du meinst. Da muß ich leider passen. Da gehts doch ziemlich ans eingemachte. Mußt du vielleicht mal bei www.linuxforen.de oder anderswo nachharken.

Man könnte ja auch eine RAM Disk in betracht ziehen, aber dann muß ich die Datei mindestens einmal kopieren. Würde sich auch nur lohnen, wenn die Datei mehrfach durchsucht werden muß.
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo nochmal,

also ums Ram wirst nicht herum kommen, nichtmal Raid-Controller können von einer Festplatte auf die andere direkt kopieren. Abgesehen davon bremst bei DMA-Platten das ram nicht, da dessen zugriffszeit doch um einiges höher liegt als bei Festplatten. Was eben aufhält, ist das Lesen/Schreiben auf Platte, nicht das Kopieren im Ram. Darum bringt hier auch C/C++ nix. Ausserdem was ist bei unterschiedlichen Festplattengeometrien, eine hat eine Blockgröße von 1024 Byte, eine andere vielleicht 2048, wohlgemerkt lowlevelmässig. Da würde so ein Direktkopieren schnell mal Müll verursachen.


Gruß

Dookie
Antworten