14 April 2009

Kompresi File

Distribusi file melalui internet seharusnya sekecil mungkin. Dengan begitu waktu untuk upload dan download akan semakin cepat. Dengan begitu akan menguntungkan kedua belah pihak, dari pengembang aplikasi maupun client. Pada beberapa saat yang lalu pernah dijelaskan tentang Borland Package Library (BPL). Aplikasi yang berisi unit-unit dan logika yang kita buat dipisahkan dengan komponen yang dipakai, yang hasil akhirnya akan mengurangi ukuran file aplikasi secara signifikan.
Tidak berheti disitu saja, masih ada cara lain lagi untuk mengurangi ukuran file yang di upload ke internet. Salah satu cara adalah dengan kompresi file. Delphi menyediakan fungsi untuk kompresi data file pada unit ZLib. ZLib merupakan library untuk keperluan kompresi dan dapat dipakai dan di download secara gratis tanpa membayar royalti. Tersedia juga source code dan dapat di download di situs http://www.zlib.net.
Dua class utama pada unit ZLib adalah TCompressionStream dan TDecompressionStream. TCompressionStream digunakan untuk kompres data. Data yang dikompres ditulis ke stream yang nantinya akan dilewatkan ke constructor TCompressionStream. Kita dapat menentukan level kompresi pada saat membuat obyek stream. Level kompresi yang disediakan adalah clNone, clFastest, clDefault, dan clMax. Untuk dekompres data kita menggunakan class TDecompressionStream.
Skrip dibawah ini untuk kompres dan dekompres file. Tidak hanya satu file saja, tapi bisa lebih dari satu. Variabel yang menyimpan nama-nama file bertipe TStrings. File kompresi ini berisi jumlah file, nama file asal, panjang nama file asal, ukuran file dan isi dari file asal.
uses Classes, SysUtils, ZLib;

procedure CompressFiles(aFiles: TStrings; const aOutFileName: string; aCompressionLevel: TCompressionLevel);
var
  infile, outfile, tmpfile: TFileStream;
  compr: TCompressionStream;
  i, j: Integer;
  s: string;
begin
  outfile := TFileStream.Create(aOutFileName, fmCreate);
  try
    j := aFiles.Count; // jumlah file
    outfile.Write(j, SizeOf(j));
    for i := 0 to aFiles.Count - 1 do
    begin
      infile := TFileStream.Create(aFiles[i], fmOpenRead);
      try
        s := ExtractFilename(aFiles[i]); // nama file asal
        j := Length(s); // panjang nama file asal
        outfile.Write(j, SizeOf(j));
        outfile.Write(s[1], j);
        j := infile.Size; // ukuran file
        outfile.Write(j, SizeOf(j));
        if j = 0 then Continue;
        tmpfile := TFileStream.Create('tmp', fmCreate);
        compr := TCompressionStream.Create(aCompressionLevel, tmpfile);
        try
          compr.CopyFrom(infile, j);
        finally
          compr.Free;
          tmpfile.Free;
        end;
        tmpfile := TFileStream.Create('tmp', fmOpenRead); // tambahkan file terkopmpresi ke file tujuan
        try
          outfile.CopyFrom(tmpFile, 0);
        finally
          tmpfile.Free;
        end;
      finally
        infile.Free;
      end;
    end;
  finally
    outfile.Free;
    DeleteFile('tmp');
  end;
end;

procedure DecompressFiles(const aFileName, aDestDirectory: string);
var
  s: string;
  decompr: TDecompressionStream;
  infile, outfile: TFileStream;
  i, j, count: Integer;
begin
  infile := TFileStream.Create(aFileName, fmOpenRead);
  try
    infile.Read(count, SizeOf(count)); // jumlah file
    for i := 1 to count do
    begin
      infile.Read(j, SizeOf(j)); // panjang nama file asal
      SetLength(s, j);
      infile.Read(s[1], j); // nama file asal
      infile.Read(j, SizeOf(j)); // ukuran file
      s := aDestDirectory + '\' + s;
      outfile := TFileStream.Create(s, fmCreate);
      decompr := TDecompressionStream.Create(infile);
      try
        if j = 0 then Continue; // antisipasi jika ukuran file = 0
        outfile.CopyFrom(decompr, j);
      finally
        outfile.Free;
        decompr.Free;
      end;
    end;
  finally
    infile.Free;
  end;
end;

Tidak ada komentar:

Posting Komentar