Seite 1 von 1

Datei häppchenweise auslesen

Verfasst: Samstag 4. April 2009, 13:40
von Twilo
Hallo,

ich möchte bzw. muss eine Datei häppchenweise auslesen

bei folgenden Codeausschnitt wird der komplette Dateiinhalt in die Variable content geschrieben; bei kleinen Dateien mag das zwar OK sein, bei Dateien die 400MB oder größer sind aber bestimmt nhicht mehr ;)

Code: Alles auswählen

def get_file_length(self, path):
    return int(svn.fs.svn_fs_file_length(self, fs_root, path))

def get_file_contens(self, path):
    stream = svn.fs.svn_fs_file_contents(self, fs_root, path)
    content = svn.core.svn_stream_read(stream, self.get_file_length())
    svn.core.svn_stream_close(stream)
    return content
wie kann bzw. muss ich die Methode get_file_contens ändern, damit ich immer eine buffer-Länge angebe, die mir zurückgegeben wird.

z.B.
get_file_contens('/trunk/a', 5) - gibt mir die ersten 5 Byte der Datei /trunk/a zurück
get_file_contens('/trunk/a', 5) - gibt mir die nächsten 5 Byte der Datei /trunk/a zurück
get_file_contens('/trunk/b', 5) - gibt mir die ersten 5 Byte der Datei /trunk/v zurück
get_file_contens('/trunk/a', 10) - gibt mir die nächsten 10 Byte der Datei /trunk/a zurück
get_file_contens('/trunk/a') - gibt mir die restlichen Bytes der Datei /trunk/a zurück
get_file_contens('/trunk/b') - gibt mir die restlichen Bytes der Datei /trunk/b zurück

das ganze müßte man dann auch pro Datei irgendwie neu starten können.

Twilo

Verfasst: Samstag 4. April 2009, 14:04
von DasIch
Es heißt content. fs_root sollte eine Konstante sein die man durchgehend groß schreiben würde oder ein Argument der Funktion get_file_contents

Dein Beispiel ist eine gewaltige Katastrophe, solche Seiteneffekte sind ziemlich böse.

Ich würde dir raten eine Klasse zu machen die sich wie eine Dateiobjekt verhält.

Verfasst: Samstag 4. April 2009, 17:00
von tordmor
Spontan hätte ich gesagt einen Generator erzeugen (yield) und in ein dictionary schreiben. Dann die neue Blockgröße mit send an den Generator schicken.

Verfasst: Samstag 4. April 2009, 19:40
von Twilo
Hallo,
DasIch hat geschrieben:Es heißt content. fs_root sollte eine Konstante sein die man durchgehend groß schreiben würde oder ein Argument der Funktion get_file_contents

Dein Beispiel ist eine gewaltige Katastrophe, solche Seiteneffekte sind ziemlich böse.
das ist kommt in einer Klasse, ich hatte jedoch vorher die grundsätzliche Funktionalität mit ipython getestet. Danach den Methodenrumpf nur noch davor geschrieben und dabei leider vergessen fs_root durch self._fs_root zu ersetzen.
die Methode soll später auch get_file_contents lauten.

Code: Alles auswählen

def get_file_length(self, path):
    return int(svn.fs.svn_fs_file_length(self, self._fs_root, path))

def get_file_contents(self, path):
    stream = svn.fs.svn_fs_file_contents(self, self._fs_root, path)
    content = svn.core.svn_stream_read(stream, self.get_file_length())
    svn.core.svn_stream_close(stream)
    return content
jetzt sollte es passen :wink:
DasIch hat geschrieben:Ich würde dir raten eine Klasse zu machen die sich wie eine Dateiobjekt verhält.
wie meinst du das?

mfg
Twilo

Verfasst: Samstag 4. April 2009, 19:57
von DasIch
Statt diesen get_file_* Kram würde ich eine Klasse haben die z.B. so aussieht.

Code: Alles auswählen

class FooFile(object):
    def __init__(self, fs_root, path):
        self.fs_root, self.path = fs_root, path
    def __len__(self):
        return int(svn.fs.svn_fs_file_length(self, self.fs_root, self.path))
    def read(self, buffer=None):
        buffer = buffer is buffer is not None else len(self)
        stream = svn.fs.svn_fs_file_contents(self, self.fs_root, self.path)
        content = svn.core.svn_stream_read(stream, buffer)
        svn.core.svn_stream_close(stream)
        return content
Da buffer eine Funktion aus bultin ist, sollte man mit dem überschreiben allerdings aufpassen.

Verfasst: Sonntag 5. April 2009, 22:34
von Twilo
Hallo,

meinst du also, innerhalb meiner Klasse eine Methode get_content, welche das FooFile-Objekt zurück gibt?

mfg
Twilo

Verfasst: Sonntag 5. April 2009, 22:39
von DasIch
Ja.

Verfasst: Montag 6. April 2009, 08:39
von Leonidas
Oder gar ein Property.

Verfasst: Montag 6. April 2009, 11:42
von Twilo
Hallo,
DasIch hat geschrieben:Ja.
ok

Code: Alles auswählen

In [1]: buffer = 5

In [2]: buffer = buffer is buffer is not None else len("12345678901234567890")
------------------------------------------------------------
   File "<ipython console>", line 1
     buffer = buffer is buffer is not None else len("12345678901234567890")
                                              ^
<type 'exceptions.SyntaxError'>: invalid syntax

Code: Alles auswählen

buffer = buffer if buffer is not None else len("12345678901234567890")
ich tippe mal, dass das erste is ein if sein muss.

So eine Syntax habe ich bisher nicht verwendet; wie ist diese zu verstehen? :)

mfg
Twilo

Verfasst: Montag 6. April 2009, 11:48
von Leonidas
Twilo hat geschrieben:So eine Syntax habe ich bisher nicht verwendet; wie ist diese zu verstehen? :)
``wert-wenn-wahr`` if ``bedingung`` else ``wert-wenn-falsch``

Das gibt es aber erst seit Python 2.5.

Aber in dem Fall ists wohl einfacher

Code: Alles auswählen

buffer = buffer or len("12345678901234567890")
zu schreiben, das tut auch auf älteren Python-Versionen und ist kürzer.

Verfasst: Montag 6. April 2009, 12:13
von Twilo
Hallo,

in php müßte es also:

Code: Alles auswählen

$buffer = &#40;$buffer === Null&#41; ? $buffer : strlen&#40;"12345678901234567890"&#41;; 
entsprechen

mfg
Twilo

Verfasst: Montag 6. April 2009, 12:31
von derdon
Auch in PHP kann man OR benutzen:

Code: Alles auswählen

$buffer = $buffer || strlen&#40;"12345678901234567890"&#41;; 

Verfasst: Montag 6. April 2009, 13:01
von Twilo
Hallo,
derdon hat geschrieben:Auch in PHP kann man OR benutzen:

Code: Alles auswählen

$buffer = $buffer || strlen&#40;"12345678901234567890"&#41;; 
das dürfte aber nur gehen, wenn buffer None/Null oder False ist

mfg
Twilo