Einzelnen Beitrag anzeigen

e-gon

Registriert seit: 7. Jul 2003
Ort: Stuttgart
163 Beiträge
 
Delphi 6 Enterprise
 
#1

Problem beim Lesen (und schreiben?) von Stream

  Alt 13. Apr 2021, 11:19
Hallo zusammen,

im Moment schreibe ich einen Editor zum Erstellen eines Brettspiel-Spielplans. Da die Autoren den Spielplan möglicherweise nicht an einem Tag erstellen oder den Plan digital weitergeben wollen, erstelle ich gerade eine Speicher- und Ladefunktion.

Während der Erstellung erlaube ich dem Autor eigene Bilder (z.B. ein eigenes Logo) einzufügen, für einzelne Elemente die Schriftart einzustellen und auch andere Einstellungen anzupassen. Das alles muss dann natürlich mit abgespeichert werden. Und da diese eigenen Bilder intern als Bitmaps vorliegen, wäre eine Komprimierung beim Speichern sehr sinnvoll.

Zur Verwirklichung stopfe ich zunächst alles in ein TMemoryStream und Komprimiere das ganze mit Hilfe von ZLib.

Das Packen und Entpacken sieht dann so aus:
Delphi-Quellcode:
procedure CompressStream(inpStream: TMemoryStream; outStream: TFileStream);
var InpBuf,OutBuf: Pointer;
     InpBytes, OutBytes: Integer;
begin
  InpBuf:= nil;
  OutBuf:= nil;

  try
    GetMem(InpBuf, inpStream.Size);
    inpStream.Position:= 0;
    InpBytes:= inpStream.Read(InpBuf^ inpStream.Size);
    CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
    outStream.Write(OutBuf^, OutBytes);
  finally
    if InpBuf<>nil then FreeMem(InpBuf);
    if OutBuf<>nil then FreeMem(OutBuf);
  end;
end;

procedure DecompressStream(inpStream: TFileStream; outStream: TMemoryStream);
var InpBuf,OutBuf: Pointer;
     OutBytes,sz: Integer;
begin
  InpBuf:= nil;
  OutBuf:= nil;
  sz:= inpStream.Size - inpStream.Position;
  if sz>0 then begin
    try
      GetMem(InpBuf, sz);
      inpStream.Read(InpBuf^, sz);
      DecompressBuf(InpBuf, sz, 0, OutBuf, OutBytes);
      outStream.Write(OutBuf^, OutBytes);
    finally
      if InpBuf<>nil then FreeMem(InpBuf);
      if OutBuf<>nil then FreeMem(OutBuf);
    end;
  end;

  outStream.Position:= 0;
end;
Das Öffnen und Speichern ist darüber verwirklicht:
Delphi-Quellcode:
var
  Projektname: string;
  BMPLogo: TBitmap; // wird bei FormCreate natürlich auch erstellt!
  Text1: string;
  Text2: string;
  Len: Integer;

procedure TForm1.ProjektSave(Filename: string);

  procedure SaveToStream(const s: AnsiString; var st: TMemoryStream); Overload;
  var l: LongInt;
  begin
    l:= Length(s);
    st.Write(l, SizeOf(l));
    if l>0 then st.Write(s[1], l);
  end;

  procedure SaveToStream(const i: LongInt; var st: TMemoryStream); Overload;
  begin
    st.Write(i, SizeOf(LongInt));
  end;

var st: TMemoryStream;
     fs: TFileStream;
begin
  fs:= TFileStream.Create(FileName, fmCreate);
  st:= TMemoryStream.Create;
  try
    SaveToStream(Projektname, st);
    BMPLogo.SaveToStream(st);
    SaveToStream(Text1, st);
    SaveToStream(Text2 ,st);
    SaveToStream(Len, st);

    CompressStream(st, fs);
  finally
    st.Free;
    fs.Free;
  end;
end;

procedure TForm1.ProjektOpen(Filename: string);

  function LoadStrFromStream(const st: TMemoryStream): AnsiString;
  var l: LongInt;
  begin
    st.ReadBuffer(l, SizeOf(l)); // -> beim ersten Durchlauf knallt es hier dann
    SetLength(Result, l);
    if l>0 then st.ReadBuffer(Result ,l);
  end;

  function LoadIntFromStream(const st: TMemoryStream): LongInt;
  begin
    st.ReadBuffer(Result, SizeOf(Result));
  end;

var st: TMemoryStream;
     fs: TFileStream;
begin
  fs:= TFileStream.Create(FileName, fmCreate);
  st:= TMemoryStream.Create;
  try
    DecompressStream(fs, st);

    Projektname:= LoadStrFromStream(st);
    BMPLogo.LoadFromStream(st);
    Text1:= LoadStrFromStream(st);
    Text2:= LoadStrFromStream(st);
    Len:= LoadIntFromStream(st);
  finally
    st.Free;
    fs.Free;
  end;
end;
Theoretisch funktioniert das Speichern (es kommt eine von der Größe her plausieble Datei heraus), aber beim Auslesen des ersten Strings bekomme ich bei st.ReadBuffer(l,SizeOf(l)) den Fehler 'Stream-Lesefehler'.

Was mache ich falsch?

Gruß
e-gon
  Mit Zitat antworten Zitat