Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi FileStream.SaveToFile verschluckt die letzten Bytes (https://www.delphipraxis.net/186479-filestream-savetofile-verschluckt-die-letzten-bytes.html)

Benmik 5. Sep 2015 20:05

Delphi-Version: 2009

FileStream.SaveToFile verschluckt die letzten Bytes
 
Ich habe einen Record in eine Klasse verpackt und speichere die Records in einer generischen TObjectList. Ich möchte jetzt die knapp 130.000 Datensätze mit einem Stream in eine Datei speichern. Hierzu verwende ich einen TFileStream und einen TReader/TWriter. Das alles klappt ohne Probleme.

Nun möchte ich gern einen TMemoryStream verwenden, um ihn mit der DEC zu ver-/entschlüsseln. Das mache ich so:
Delphi-Quellcode:
procedure TZielListe.SaveToFile(Dateiname:string;PW:string = '');
var Writer: TWriter; Stream:TMemoryStream; i:integer;
begin
  Stream := TMemoryStream.Create;
  Writer:= TWriter.Create(Stream, 4096);
  Try
    Writer.WriteListBegin;
    For i := 0 to Self.Count - 1 do begin
      Writer.WriteInteger(Self[i].Int1);
      Writer.WriteInteger(Self[i].Int2);
      Writer.WriteString(Self[i].Text1);
      Writer.WriteString(Self[i].Text2);
      Writer.WriteInteger(Self[i].Int64A);
      Writer.WriteInteger(Self[i].Int64B);
      Writer.WriteInteger(Self[i].Int64C);
    end;
    Writer.WriteListEnd;
    Stream.SaveToFile(Dateiname);
  Finally
    Writer.Free;
    Stream.Free;
  End;
end;
Nunmehr knallt es aber beim Einlesen. Nach mühseliger Suche habe ich mit einem Hexeditor herausgefunden, dass das daran liegt, dass nicht alle Bytes in die Datei geschrieben werden. Der Fehler hat mit der Größenangabe bei
Delphi-Quellcode:
Writer:= TWriter.Create(Stream, 4096);
zu tun. Der letzte Block wird offenbar nicht geschrieben. Nehme ich eine durch 16 teilbare Größe, so werden die letzten über 16 hinausstehenden (hier 4) Bytes nicht mitgespeichert. Nehme ich eine Größe von 1, so wird das letzte Byte nicht geschrieben (nämlich das
Delphi-Quellcode:
Writer.WriteListEnd;
). Nehme ich eine andere Größe (15, 1024 oder 4096), so wird ein entsprechend großer Rest nicht geschrieben.

Weiß jemand, was hier vorgeht?

jbg 5. Sep 2015 21:45

AW: FileStream.SaveToFile verschluckt die letzten Bytes
 
TWriter nutzt einen Puffer, der erst durch das Free in den Stream übertragen wird. Du musst also das Writer.Free vor das Stream.SaveToFile verschieben.
Alternativ kannst du vor dem Stream.SaveToFile ein "Writer.FlushBuffer" einbauen.

Benmik 5. Sep 2015 22:47

AW: FileStream.SaveToFile verschluckt die letzten Bytes
 
Danke, das war's! :thumb:

Ich finde es unmöglich, dass man nirgendwo darauf hingewiesen wird. "FlushBuffer" wird als nur für den internen Gebrauch beschrieben, und was "Free" bewirkt, überhaupt nicht. Da wäre ich nun nie drauf gekommen. Also Danke nochmals.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:22 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz