![]() |
Datei stückchenweise mit TFileStream einlesen
Ich versuche eien Datei stückchenweise mit ReadBuffer einzulesen, den Buffer zu verarbeiten und dann das Ganze wieder zu schreiben.
Delphi-Quellcode:
Aber das will nicht so recht. Ich bekomme da immer einen Stream.Lesefehler. Es hadelt sich um alle möglichen Dateien, binär, Text, typisierte, ...
var
SrcBuffer, DestBuffer: cardinal; begin while SrcStream.Position < SrcStream.Size do begin SrcStream.ReadBuffer(SrcBuffer, 1024); EncodeBuffer(SrcBuffer, DestBuffer, 1024); DestStream.WriteBuffer(DestBuffer, 1024); end; So geht es auch nicht:
Delphi-Quellcode:
Gleiche Fehler.
var
SrcBuffer, DestBuffer: Pointer; begin GetMem(SrcBuffer, 1024); GetMem(DestBuffer, 1024); while DestStream.Size < SrcStream.Size + sizeof(TFileHeader) do begin SrcStream.ReadBuffer(SrcBuffer, 1024); EncodeBuffer(SrcBuffer, DestBuffer, 1024); DestStream.WriteBuffer(DestBuffer, 1024); end; |
Re: Datei stückchenweise mit TFileStream einlesen
In eine cardinal Variable passen nur 32 Bit...
Nimm ein Array:
Code:
Du kannst auch mit pointer arbeiten:
var
SrcBuffer, DestBuffer: array[0..1023] of byte; begin while SrcStream.Position < SrcStream.Size do begin SrcStream.ReadBuffer(SrcBuffer[0], 1024); EncodeBuffer(SrcBuffer[0], DestBuffer[0], 1024); DestStream.WriteBuffer(DestBuffer[0], 1024); end;
Code:
SrcBuffer, DestBuffer: pointer;
begin getmem(SrcBuffer, 1024); getmem(DeasBuffer, 1024); try while SrcStream.Position < SrcStream.Size do begin SrcStream.ReadBuffer(SrcBuffer^, 1024); EncodeBuffer(SrcBuffer^, DestBuffer^, 1024); DestStream.WriteBuffer(DestBuffer^, 1024); end; finally freemem(SrcBuffer); freemem(DestBuffer); end; |
Re: Datei stückchenweise mit TFileStream einlesen
Ha, da war ich doch gar nicht soweit weg. Blos die Abbruchbedingung stimmt noch nicht ganz. Ich schreibe in den ZielStream erst einen Header und dann den QuellStream. Nur mit
Delphi-Quellcode:
Bekomme ich zum Schluß wieder einen Stream-Lesefehler.
while SrcStream.Position < SrcStream.Size do
|
Re: Datei stückchenweise mit TFileStream einlesen
Code:
var
Len: integer; ... begin ... while SrcStream.Position < SrcStream.Size do begin Len:=(SrcStream.Size-SrcStream.Position) mod 1025; SrcStream.ReadBuffer(SrcBuffer^, Len); EncodeBuffer(SrcBuffer^, DestBuffer^, Len); DestStream.WriteBuffer(DestBuffer^, Len); end; ... |
Re: Datei stückchenweise mit TFileStream einlesen
Der Schuß ins Blaue ging daneben. Len ist immer 0. Er liest und schreibt also gar nichts.
|
Re: Datei stückchenweise mit TFileStream einlesen
Code:
Bin schon ein wenig müde...
if SrcStream.Size-SrcStream.Position>1024 then
Len=1024 else Len:=SrcStream.Size-SrcStream.Position; |
Re: Datei stückchenweise mit TFileStream einlesen
Perfekt, der saß genau im Bulleseye. Besten Dank.
|
Re: Datei stückchenweise mit TFileStream einlesen
Da fällt mir noch ein:
Falls du statt ReadBuffer Read nimmst, dann kannst du es so machen:
Code:
var
Len: integer; ... begin ... while SrcStream.Position < SrcStream.Size do begin Len:=SrcStream.Read(SrcBuffer^, 1024); EncodeBuffer(SrcBuffer^, DestBuffer^, Len); DestStream.WriteBuffer(DestBuffer^, Len); end; ... |
Re: Datei stückchenweise mit TFileStream einlesen
Hm, Jetzt hab eich es so, aber die zweite Lösung wäre wohl performanter, da die if-Abfrage wegfällt. Und da waren sie wieder meine drei Problem... Stream-Lesefehler.
|
Re: Datei stückchenweise mit TFileStream einlesen
Moin Luckie,
komisch. An welcher Stelle denn? Im Prinzip müsste es auch so gehen:
Delphi-Quellcode:
Statt eines Strings wie bei mir kannst Du natürlich auch einen anderen Buffer (array of char) nehmen.
iLen := fsIN.Read(sBuf[1],iBlockSize);
while iLen > 0 do begin fsOUT.Write(sBuf[1],iLen); iLen := fsIN.Read(sBuf[1],iBlockSize); end; Lesefehler dürftest Du nur bei ReadBuffer bekommen, nicht bei Read. |
Re: Datei stückchenweise mit TFileStream einlesen
Und genau das sind meine zwei andern Probleme: Es müßte gehen und ich verstehe nicht, warum es nicht geht. :roll:
|
Re: Datei stückchenweise mit TFileStream einlesen
Moin Luckie,
bekommst Du wirklich bei SrcStream.Read den Fehler? :shock: Wie sieht die Routine denn bei Dir aus. Am Besten incl. Datendeklaration, und Dateigrösse (genau) |
Re: Datei stückchenweise mit TFileStream einlesen
Jupp, ich bekomme einen. Deklarationen wie gehabt (siehe oben). UInd ausgesehen hat sie wie von Kamil gepostet. Dateigröße: 49.955.924 Bytes. GetMem habe ich auch aufgerufen.
Keinen Plan. Habe es aber schon wieder rückgängig gemacht. Wenn ich die if-Konstruktion nehme und statt 1024 2048 oder 4096 einsetze, bekomme ich eine AccessViolation zum Schluß. |
Re: Datei stückchenweise mit TFileStream einlesen
Delphi-Quellcode:
Wichtig! EncodeBuffer() sollte nach Möglichkeit inplaced arbeiten.
var
Len: integer; Buffer: array[0..1023] of Byte; ... begin ... while SrcStream.Position < SrcStream.Size do begin Len := SrcStream.Size - SrcStream.Position; if Len > SizeOf(Buffer) then Len := SizeOf(Buffer); SrcStream.Read(Buffer, Len); EncodeBuffer(Buffer, Buffer, Len); DestStream.WriteBuffer(Buffer, Len); end; ... oder
Delphi-Quellcode:
Dies vermeidet die Seek-Aufrufe in den Dateistream durch das OS um .Position und .Size zu berechnen. Dadurch wird also der Dateistream nur sequentiell gelesen und dies ist erheblich schneller !! Probier es aus mit großen Files.
var
Len: integer; Buffer: array[0..1023] of Byte; ... begin ... repeat Len := SrcStream.Read(Buffer, SizeOf(Buffer)); // .Read statt .ReadBuffer um Exceptions zu vermeiden EncodeBuffer(Buffer, Buffer, Len); DestStream.WriteBuffer(Buffer, Len); until Len = 0; ... end; Gruß Hagen |
Re: Datei stückchenweise mit TFileStream einlesen
Geil. Werde ich gleich ausprobieren. Besten Dank.
PS: Steht das im DEC irgendwo, dass EncodeBuffer inplaced arbeiten sollte? Oder ist das allgemeines Kryptologiewissen? |
Re: Datei stückchenweise mit TFileStream einlesen
So jetzt haben wir den Salat, jetzt bekomme ich unterschiedliche Hash-Werte nach dem Entschlüsseln und die entschlüsselte Datei ist dann natürlich nicht zu gebrauchen.
|
Re: Datei stückchenweise mit TFileStream einlesen
Entschlüsseln:
Delphi-Quellcode:
Verschlüsseln:
// ignore the file header
SrcStream.Seek(sizeof(TFileHeader), soFromBeginning); // assign the Cipherclass CipherClass := Cipher; // prepare for decoding with CipherClass.Create(PW, nil) do begin Mode := cmCFB; InitKey(PW, nil); // as long as we have not reached the end of the source stream repeat Len := SrcStream.Read(Buffer, SizeOf(Buffer)); EncodeBuffer(Buffer, Buffer, Len); DestStream.WriteBuffer(Buffer, Len); until Len = 0; end;
Delphi-Quellcode:
Was habe ich übersehen?
// write the head into the stream
DestStream.Write(FileHeader, sizeof(TFileHeader)); // prpare vor encoding with CipherClass.Create(PW, nil) do begin Mode := cmCFB; InitKey(PW, nil); // as long as Len has something to read repeat Len := SrcStream.Read(Buffer, SizeOf(Buffer)); EncodeBuffer(Buffer, Buffer, Len); DestStream.WriteBuffer(Buffer, Len); until Len = 0; end; |
Re: Datei stückchenweise mit TFileStream einlesen
Zitat:
Wird inplaced gearbeitet so werden die Daten im Buffer implizit mit deren verschlüsseltem Produkt überschrieben. Da .EncodeBuffer() nicht wissen kann ob der Anwender seine Daten geschützt haben will darf .EncodeBuffer() auch nicht den Sourcebuffer von sich aus mit Müll füllen. Dies müsste dann schon deine Funktion machen damit eben keine sicherheitsrelevanten Daten im Speicher verbleiben. Übrigens: dies ist auch der Grund warum ich den Buffer NICHT dynamisch alloziere sondern im Stack ablege. Bei dynamischen Speicher müsstest du wiederum dafür Sorge tragen das er wiped wird. Im Stack wird mit enorm hoher Wahrscheinlichkeit der Stackspeicher durch nachfolgende Funktionen nochmals überschrieben. Geht man davon aus das es heute Techniken gibt die aus benutzten Speicherzellen denoch deren Inhalt vor 100 Schreibänderungen ermitteln können, so wird klar das der Stack zB. einer der Speicherbereiche ist der die meisten Schreibänderungen hat. Die Lebenszeit der sichertsrelevanten Daten bei inplaced Codierungen ist die kürzt mögliche. Das Tracen des Stackes ist eine der schwierigsten Operationen eines guten Debuggers. All diese Überlegungen kann ein Programmierer ohne viel Aufwand umsetzen um seine Kryptofunktionen sicherer zu machen. Zitat:
Gruß hagen |
Re: Datei stückchenweise mit TFileStream einlesen
Zitat:
Zitat:
Zitat:
Gruß Hagen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:44 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz