Avatar billede friiiiis Novice
19. marts 2007 - 16:08 Der er 11 kommentarer og
1 løsning

Gem af datafiler vha. TFilestream

Hej,

Jeg bruger TFilestream til at gemme nogle meget store datastrukturer i - det virker OK, men det er LANGSOMT!! - synes ikke det gør "gemningen" af datastrukturerne hurtigere end det at gemme i .txt vha. writeln.

Vil det sige at den eneste fordel ved at bruge TFilestream fremfor simpel ASCII filer (*.txt) er at den kan gemme en linien længere end 255 karakterer? TFilestream er altså hverken hurtigere eller bedre til at komprimere dataene?

Er der en anden måde at gemme meget store datamænder på HURTIGT og gerne også komprimeret?
Avatar billede martinlind Nybegynder
19. marts 2007 - 19:07 #1
Du putter det ind i en TStream-noget og så bruger zlib til at pakke den med, den kører på stream's og så gemmer du til disk.
Avatar billede martinlind Nybegynder
19. marts 2007 - 19:09 #2
uses ZLib;
Avatar billede martinlind Nybegynder
19. marts 2007 - 19:09 #3
VAR
  FComp : TStream;
  FBuf  : Cardinal;
begin
  try
    if FExecuteMode = cfCompress then
    begin
        FBuf := FSourceStream.Size;
        FDestStream.Write(FBuf,SizeOf(FBuf));
        FComp := TCompressionStream.Create(clMax,FDestStream);
        TCompressionStream(FComp).OnProgress := FOnProgress;
        FComp.CopyFrom(FSourceStream,soFromBeginning);
    end else
    if FExecuteMode = cfExpand then
    begin
        FSourceStream.Read(FBuf,SizeOf(FBuf));
        // ??? if FOrgSize <> FBuf then FBuf := FOrgSize;
        FComp := TDeCompressionStream.Create(FSourceStream);
        TDeCompressionStream(FComp).OnProgress := FOnProgress;
        FDestStream.CopyFrom(FComp,FBuf);
    end;
  finally
      FreeAndNil(FComp);
  end;
end;
Avatar billede martinlind Nybegynder
19. marts 2007 - 19:11 #4
Jeg har brugt noget med en OrgSize fordi det skulle man bruge til udpakning, den gang jeg brugte zlib, så du må kigge i hjælpen for at se om man stadig skal det
Avatar billede martinlind Nybegynder
19. marts 2007 - 19:14 #5
du kan også teste med en TStringList, det brugte jeg på et tidspunkt med stort held, fordi jeg havde den samme oplevelse som dig, stringlist var mærkbart den hurtigste måde, af uforklarlige årsager :)
Avatar billede friiiiis Novice
19. marts 2007 - 22:59 #6
Hej,

MANGE tak for svaret - jeg accepterer det naturligvis og du får pointene... men kan du ikke lige hjælpe lidt mere - jeg er lidt grøn mht. TStream, Tbuffer etc. - hvordan "putter" jeg en string ind i Tstream i en for-løkke og hvordan gemmer jeg filen med et eller andet filnavn?

Iøvrigt - hvad betyder "sofrombeginning" i din kode herover?
Avatar billede martinlind Nybegynder
20. marts 2007 - 09:28 #7
At Copy er fra-begyndelsen af streamen ( Position = 0 )
Avatar billede martinlind Nybegynder
20. marts 2007 - 09:29 #8
// Push and Pop helper functions
function GetStr(AStream: TStream): String;
VAR
  Len : Integer;
begin
  AStream.Read(Len,SizeOf(Len));
  Result := '';
  if Len > 0 then
  begin
      SetLength(Result,Len);
      AStream.Read(Result[1],Len);
  end;
end;

procedure PutStr(AStr: String; AStream: TStream);
VAR
  Len : Integer;
begin
  Len := Length(AStr);
  AStream.Write(Len,SizeOf(Len));
  if Len > 0 then AStream.Write(Astr[1],Len);
end;

function GetInt( aStream : TStream ) : Integer;
begin
  AStream.Read(Result,SizeOf(Result));
end;

procedure PutInt( aInt : Integer; AStream : TStream );
begin
  AStream.Write(aInt,SizeOf(aInt));
end;

function GetFloat( aStream : TStream ) : Double;
begin
  AStream.Read(Result,SizeOf(Result));
end;

procedure PutFloat( aFloat : Double; AStream : TStream );
begin
  AStream.Write(aFloat,SizeOf(aFloat));
end;

function GetStream( aStream : TStream ) : TStream;
VAR
  Len : Integer;
begin
  Result := TMemoryStream.Create;
  AStream.Read(Len,SizeOf(Len));
  if Len > 0 then Result.CopyFrom(aStream,Len);
  Result.Position := 0;
end;

procedure PutStream( aValue,aStream : TStream );
VAR
  Len : Integer;
begin
  Len := aValue.Size;
  AStream.Write(Len,SizeOf(Len));
  aValue.Position := 0;
  AStream.CopyFrom(aValue,Len);
end;
Avatar billede martinlind Nybegynder
20. marts 2007 - 09:30 #9
Ellers er det online hjælpen på TFileStream :)
Avatar billede friiiiis Novice
20. marts 2007 - 10:01 #10
Hej,

Lige et sidste spørgsmål - skal jeg skrive strings ind i Tstream og når alle strings er i TStream så benytter jeg TCompressionstream - eller skal jeg skrive fra strings til TStream til TCompression kontinuerligt?
Avatar billede martinlind Nybegynder
20. marts 2007 - 13:11 #11
Hæld dinne data ind i en stream ( der er af passende type ) og pak den og gem den, læs den ind pak den ud så du ender med en TStream af den type du skal bruge :)
Avatar billede friiiiis Novice
21. marts 2007 - 14:48 #12
For en god ordens skyld kommer her noget kode der kan løse problemet:

Koden herunder pakker en stringlist i en fil benævnt "compressedfile.dat"

var
StringList : TStringlist;
FileStream : TFileStream;
infile, outfile : TFileStream;
MStream :TMemoryStream;
compr : TCompressionStream;
l : Integer;
begin

...
...
...


MStream := TMemoryStream.Create;
StringList.SaveToStream(MStream);

outFile := TFileStream.Create('CompressedFile.dat',fmCreate);

    try
      l := MStream.Size;
      outfile.Write(l,SizeOf(l));
      compr := TCompressionStream.Create(clMax,outfile);
      compr.CopyFrom(MStream,0);
    finally
      compr.Free;
      outfile.Free;
      MStream.Free;
    end;
end;

Koden herunder dekomprimere filen fra herover og ligger den ned i en ny fil benævnt "Decompressed.dat"



var
  decompr : TDecompressionStream;
  outfile : TFilestream;
  l : Integer;
  stream :TMemoryStream;
begin

...
...
...


stream := TMemorystream.Create;
stream.LoadFromFile('CompressedFile.dat');
stream.Read(l,sizeof(l));

outfile := TFileStream.Create('Decompressed.dat',fmCreate);
decompr := TDecompressionStream.Create(Stream);
try
  outfile.CopyFrom(decompr,l);
finally
  outfile.Free;
  decompr.Free;
  stream.Free;
end;

end;
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester