FILE.read() liest nicht alle daten

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
kekschaot
User
Beiträge: 2
Registriert: Sonntag 5. Februar 2012, 07:04

Guten Morgen Forum,


mein Problem ist, dass ein

Code: Alles auswählen

FILE.seek(offset)
buffer = FILE.read()
nicht das gewünschte Ergebniss (nämlich vom offset bis EOF in den buffer zu schreiben) bewirkt.
Vielleicht mache ich einen erheblichen Denkfehler?

Code: Alles auswählen

#!/usr/bin/env python

from time import sleep


def split_file(file="C:/calc.exe",bytes=10000,zfill=10): # generate files each $bytes bytes smaller
    try:
        FILE = open(file,"r",100000000)

    except all:
        print "Could not open "+file+" for reading!"
        exit

    offset = 0
    while FILE:
        FILE.seek(offset)
        print "Set to offset: " + str(offset)
        buffer = FILE.read()
        print "Bufferlen: "+ str(len(buffer))

        FILE.seek(offset) # seek again because FILE.read() sets the cursor to EOF

        if len(buffer) == 0: # EOF reached
            quit()

        nfilename = file+str(offset).zfill(zfill) # gen filename; fill with zeros

        try:
            NFILE = open(nfilename,"w",0)
            print nfilename + " created!\n"

        except all:
            print nfilename + " could not be created!"


        NFILE.write(buffer) # write all stuff to the new (smaller) file
        NFILE.close()
        offset = offset + bytes # gen new file cursor position

    FILE.close()


def main():
    split_file()

if __name__ == '__main__':
    main()

Liebe Grüße
Keks

EDIT:

Die Ausgabe des Scriptes. Ich erwarte eigentlich dass die Bufferlen immer um $bytes kleiner wird, was sie offensichtlich nicht macht!:

Code: Alles auswählen

Set to offset: 0
Bufferlen: 1468
C:/calc.exe0000000000 created!

Set to offset: 10000
Bufferlen: 3762
C:/calc.exe0000010000 created!

Set to offset: 20000
Bufferlen: 1831
C:/calc.exe0000020000 created!

Set to offset: 30000
Bufferlen: 903
C:/calc.exe0000030000 created!

Set to offset: 40000
Bufferlen: 3171
C:/calc.exe0000040000 created!

Set to offset: 50000
Bufferlen: 9101
C:/calc.exe0000050000 created!

Set to offset: 60000
Bufferlen: 2247
C:/calc.exe0000060000 created!

Set to offset: 70000
Bufferlen: 1610
C:/calc.exe0000070000 created!

Set to offset: 80000
Bufferlen: 8923
C:/calc.exe0000080000 created!

Set to offset: 90000
Bufferlen: 376
C:/calc.exe0000090000 created!

Set to offset: 100000
Bufferlen: 14688
C:/calc.exe0000100000 created!

Set to offset: 110000
Bufferlen: 4688
C:/calc.exe0000110000 created!

Set to offset: 120000
Bufferlen: 0 80000
Bufferlen
Zuletzt geändert von Anonymous am Sonntag 5. Februar 2012, 09:40, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mal ins Blaue geraten (hab kein Windows hier): Was passiert, wenn du die `calc.exe` im Modus `rb` (für Binärdatei) öffnest?
kekschaot
User
Beiträge: 2
Registriert: Sonntag 5. Februar 2012, 07:04

Danke snafu, dass war das Problem!

EDIT:

hier fehlte auch der binary mode:
try:
NFILE = open(nfilename,"wb")
print nfilename + " created!\n"
except all:
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

kekschaot hat geschrieben:Danke snafu, dass war das Problem!
Ich hätte da noch zwei Hinweise bezüglich der Namensgebung für Bezeichner.

Du solltest eigene Bezeichner nicht so nennen wie eingebaute Funktionen. file ist so ein Fall. Du überschreibst damit die eingebaute Funktion.

Bezeichner in Großbuchstaben stehen laut Konvention für Konstanten. NFILE wird aber nicht als Konstante verwendet.

Schau dir einfach mal den Style Guide for Python Code an.
BlackJack

@kekschaot: Noch ein paar Anmerkungen zum Programm:

Namen komplett in Grossbuchstaben sind per Konvention für Konstanten gedacht, `FILE` ist aber keine Konstante.

Das Argument `file` bei `split_file()` ist keine Datei sondern ein Dateiname, sollte deshalb auch besser `filename` heissen. Die Vorbelegung des Arguments mit einer ``calc.exe`` die im Hauptverzeichnis von Laufwerk C liegt, ist IMHO ein wenig *sehr* spezifisch.

Dateien sollte man mit der ``with``-Anweisung öffnen, dann muss man sich keine Gedanken darum machen, dass die Datei wieder geschlossen wird.

``except all:`` macht nicht das was Du denkst. `all()` ist eine Funktion. Die wird sicher nirgends als Ausnahme verwendet, also ist es sinnfrei damit ein ``except`` zu schreiben. Der Fall wird einfach niemals eintreten.

Funktionsnamen einfach nur hin zu schreiben reicht nicht wenn man sie auch *aufgerufen* haben möchte. Siehe ``exit`` im ersten sinnfreien ``except all:``-Zweig.

``while FILE:`` ist irreführend, weil ein Dateiobjekt in dem Kontext *immer* wahr ist. Dann sollte man aber auch direkt ``while True:`` schreiben um den Leser nicht unnötig zu verwirren.

``+`` und `str()` um Zeichenketten zusammen zu setzen ist eher BASIC als Python. Bei ``print`` kann man sich das sparen wenn man mehrere Ausdrücke durch Kommas getrennt angibt, und sonst ist eher Zeichenkettenformatierung mittels ``%``-Operator oder `format()`-Methode auf Zeichenketten üblich.

Das zweite `FILE.seek()` ist unnötig, denn danach wird auf die Datei nicht mehr zugegriffen bevor am Anfang des nächsten Schleifendurchlaufs *nochmal* die Methode mit einem anderen Versatz aufgerufen wird.

`quit()` sollte man nicht verwenden. Die Funktion existiert für die interaktive Shell sollte aber nicht in Programmen verwendet werden, da das vorhandensein nicht garantiert ist. Die Dokumentation dazu:
http://docs.python.org/library/constants.html#constants-added-by-the-site-module hat geschrieben:The site module (which is imported automatically during startup, except if the -S command-line option is given) adds several constants to the built-in namespace. They are useful for the interactive interpreter shell and should not be used in programs.
Ansonsten gibt es auf einer höheren Ebene zwei Punkte:

1. Die Quelldatei wird unnötig oft gelesen. Beim ersten Lesen wird doch schon die komplette Datei in den Speicher gelesen — warum nicht von den Daten dann immer kleiner werdende Teile speichern?

2. Das Programm funktioniert nur so lange vernünftig, wie die komplette Datei in den Arbeitsspeicher passt.
Antworten