Delphi - Állománykicsomagoló komponens

A Delphi rejtett képességei 2. rész

forráskód letöltése
Múlt heti cikkünkben készítettünk egy olyan komponenst, mellyel tetszőleges számú állományt tömöríthettünk össze. Mostani cikkünkben elkészítjük azt a komponenst, mely képes ezeknek a tömörített állományoknak a kicsomagolására. A mellékelt példaprogram megnyitása előtt a Decompress.pas-ban lévő komponenst telepítenie kell a Delphi alá. További szükséges előkészület a Zlib forráskódjainak telepítése. Ennek részletes leírását a múlt heti cikkben megtalálja.

A komponens használatához adja meg azt a könyvtárat a ZlibDir property-ben, ahol a TCompress komponens által tömörített állományok találhatók.

A DecompressDir property-ben adja meg azt a könyvtárat, ahová szeretné elhelyezni a kicsomagolt állományokat.

A kicsomagolást az Execute hívásával tudja elindítani. Futása közben az OnProgress esemény felhasználásával lehet nyomon követni a folyamat aktuális állapotát.

Az OnFilter esemény felhasználásával szűrhetjük, hogy mely állományok kerüljenek kicsomagolásra és melyek ne. Az esemény FileName paraméterében kapjuk a kicsomagolandó állomány nevét. Ha az Enabled paraméternek hamis értéket adunk, akkor a kicsomagolás elmarad.

Az Execute eljárás hívásakor futtatjuk a DecompressOneDir belső eljárásunkat. Itt a FindFirstFile - FindNextFile - FindClose függvényekkel elvégezzük a megadott könyvtárban található állományok keresését. Amikor találunk egy állományt, melynek a kiterjesztése a TCompress komponens által létrehozott zlib kiterjesztésű állomány, akkor a DecompressOneFile eljárást hívjuk meg, paraméterként átadva a talált állomány nevét. Ez az eljárás végzi el az adott állomány kicsomagolását.
procedure TDecompress.DecompressOneDir(source: string);
var
  h: THandle;
begin
  h:=FindFirstFile(PChar(source+'*.*'), FD);
  if h<>INVALID_HANDLE_VALUE then begin
    repeat
      if FD.cFileName[0]<>'.' then begin
        if not (FD.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY=
             FILE_ATTRIBUTE_DIRECTORY) then begin
          if Uppercase(ExtractFileExt(FD.cFileName))=
               '.ZLIB' then begin
            DecompressOneFile(source+FD.cFileName);
          end;
        end;
      end;
    until not FindNextFile(h, FD);
    Windows.FindClose(h);
  end;
end;
A kicsomagolás előtt meghívjuk az OnFilter eseményt, ha van hozzárendelve eseménykezelő. Ha nem kerül elutasításra az adott állomány, akkor a Zlib TDecompressionStream osztálya segítségével elvégezzük a kicsomagolást.
procedure TDecompress.DecompressOneFile(source: string);
const
  BUFFERSIZE=524288;
var
  fs, fd: TFileStream;
  count: integer;
  cs: TCustomZlibStream;
  buffer: array[0..BUFFERSIZE-1] of byte;
  s: string;
  b: boolean;
begin
  b:=true;
  if Assigned(FOnFilter) then begin
    FOnFilter(Self, source, b);
  end;
  if b then begin
    fs:=TFileStream.Create(source, fmOpenRead);
    s:=FDecompressDir+ExtractFileName(source);
    Delete(s, Length(s)-4, 5);
    fd:=TFileStream.Create(s, fmCreate);
    cs:=TDecompressionStream.Create(fs);
    (cs as TDecompressionStream).OnProgress:=DoProgress;
    repeat
      count:=cs.Read(buffer, BUFFERSIZE);
      if count<>0 then begin
        fd.WriteBuffer(buffer, count);
      end;
    until count=0;                       
    DoProgress(nil);
    cs.Free;
    fd.Free;
    fs.Free;
  end;
end;

A Delphi rejtett képességei cikksorozat