Einzelnen Beitrag anzeigen

Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#3

Re: Datei in Streams zerstückeln

  Alt 25. Mär 2007, 20:16
Zitat von TurboMartin:
Ich möchte unter Verwendung diesen Codes eine Sehr große Datei in einen Stream laden. So weit so gut.
Hi,
ich glaube da hast Du die Theorie von Streams noch nicht so richtig verstanden. Ein Stream ist eigentlich nur eine Art Verbindung zwischen zwei Punkten. Etwas unsauber kann man hier vielleicht besser von einem Kanal als Strom sprechen. Du kannst Daten zwischen zwei Endpunkten hin- und her bewegen. Beim Schreiben in den Stream landen die Daten nicht direkt im Stream, sondern dort, wo dieser Stream (Kanal) endet. Liest Du Daten aus dem Stream, so werden sie von diesem Endpunkt gelesen und nur über den Stream zu Dir transportiert. Der Stream selbst hält dabei nicht wirklich die Daten.
Wo diese gespeichert werden hängt mit der Implementierung der abstrakten Klasse TStream zusammen. Hier kommen Strings, Dateien, Speicherblöcke, aber auch alles andere in Frage.

Für eine Datei empfiehlt sich natürlich ein TFileStream. Erzeugst Du nun einen TFileStream, so wird zu keinem Zeitpunkt die ganze Datei in den Speicher geladen. Du erzeugst nur einen Kanal, der Daten in die Datei (bzw. aus ihr heraus) transportieren kann.

Zitat von TurboMartin:
Da sie sehr groß ist möchte ich dies nun in bestimmt große Blöcke zerkleinern. Das bedeutet, das ich in den Stream z.B. maximal 30MB geladen werden können.
Wenn Du mit Blöcken arbeiten willst, dann kannst Du einfach einen Puffer von 30 MByte erzeugen (z.B. ein String der Länge 30 * 1024 * 1024). Nun liest Du einfach die 30 MByte in diesen Puffer ein und arbeitest mit diesem weiter. Dein Stream wird dabei nur die Daten in den Speicher laden, die wirklich gerade gelesen werden. Dabei verwendet der Stream zwar einen Lesepuffer, aber auch dieser dürfte nicht all zu groß sein, so dass Du hier keine Sorgen haben musst.
Delphi-Quellcode:
var fs: TFileStream;
    buffer: String;
    count: Integer;
begin
  fs := TFileStream.Create(...);

  try
    // erzeugen eines 30 MByte Puffers
    setLength(buffer, 30 * 1024 * 1024);
    
    // Lesen der Datei in 30 Mbyte Blöcken
    repeat
      count := fs.Read(buffer[1], 30 * 1024 * 1024);
      
      // weiterarbeiten mit dem String
      // Achtung, Count gibt an wie viele Bytes vom Puffer
      // wirklich verwendet werden, der letzte String muss
      // nicht die vollen 30 MByte umfassen
      ....
    until count < 0;
  finally
    fs.Free;
  end;
Zitat von TurboMartin:
Nun ist meine Frage, wie ich in einen Stream nur maximal 30MB lden kann, und diese dann nacher wieder zusammensetzten kann.
Beim Zusammensetzen gilt das Gleiche wie gehabt (nur in schreibend). Du kannst die Blöcke von 30 MByte irgendwie verarbeiten. Dann bekommst Du irgendwas raus, das Du dann eben wieder in einen Stream schreibst. Handelt es sich bei dem Stream, in den Du schreibst um einen FileStream, landen die Daten direkt auf der Platte und nicht im Speicher (sehen wir von Caches und Lese/Schreibpuffer ab, die für Dich eh transparent sind).

Gruß Der Unwissende

[edit]
kein roter Kasten, sorry
[/edit]
  Mit Zitat antworten Zitat