Staňte se programátorem: Napiště si vlastní WinZip

Pevné disky sice mají stále větší kapacitu, občas je ale potřeba něco zabalit. Napište si s námi archivátor, který použije Zip, bude umět nastavit míru komprese a zvládné i ochranu heslem.

Od loňského léta jste si s námi mohli naprogramovat jednoduchý textový editor, bitmapový editor s několika fotografickými filtry nebo webový prohlížeč s podporou surfování v záložkách. Vyzkoušeli jsme si ale i tvorbu kontroverzního špiona, který na pozadí běhu Windows snímal aktivitu klávesnice a odesílal stisknuté klávesy a obraz plochy na e-mail. Naprogramovali jsme si také jednoduchý adresář kontaktů pomocí několika technik, zjistili jsme, že vývoj v C# je celkem snadný i na Linuxu a naposledy jste se mohli seznámit s několika napodobeninami zajímavých efektů některých akcelerovaných linuxových grafických desktopů.

Zipper

Dnes si napíšeme jednoduchý archivovací program Zipper, který zabalí pomocí formátu Zip libovolné množství souborů. Výsledný balík budete moci obdařit heslem a samozřejmě nebude chybět ani možnost nastavení úrovně komprese. K samotné kompresi zároveň poprvé v našem seriálu použijeme externí dynamickou knihovnu, práce tedy bude o to jednodušší.

zipper.png    zipper2.png  archiv.png
Výběr souborů ke komprimaci, zadání hesla a snaha o rozbalení v běžném archivačním programu (WinRAR)

Externí knihovna #ZipLib

Prostředí .NET Framework neumožňuje práci s kompresními formáty, a tak je zapotřebí využít externí knihovnu. K našemu účelu nám poslouží knihovna #ZipLib, kterou najdete na této adrese. Knihovnu jednoduše importujeme do našeho projektu z menu Project -> Add Reference a v kartě Browse vybereme požadovanou knihovnu. Vzápětí bude v projektu vytvořen odkaz na tuto knihovnu. Jednotlivé třídy knihovny jsou uloženy ve jmenném prostoru ICSharpCode.SharpZipLib. Jelikož chceme pracovat se Zip balíky, použijeme třídy uložené ve jmenném podprostoru Zip. Jmenné prostory knihovny tedy zpřístupníme direktivou

using ICSharpCode.SharpZipLib.Zip;

Komprimace souborů do Zip archívu

Pro zkomprimování více souborů do Zip archívu slouží třídy ZipOutputStream vytvářející datový proud k budoucímu *.zip souboru. Jednotlivé archivované soubory jsou představovány třídou ZipEntry a do komprimačního proudu jepřidáme metodou PutNextEntry.

// Zobrazí dialog pro výběr místa, kam bude zip soubor uložen
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == DialogResult.OK)
{
  textBox2.Text = sfd.FileName;
}

string[] filenames = list.ToArray();

// Vytvoří datový proud k budoucímu zip souboru
ZipOutputStream s = new ZipOutputStream(File.Create(this.textBox2.Text + ".zip"));
{
  // Nastaví heslo
  s.Password = textBox1.Text;
  // Hodnoty 0 - 9 nastavují úroveň komprimace
  s.SetLevel((int)numericUpDown1.Value); 
  byte[] buffer = new byte[4096];
  // Projde jednotlivé soubory, jež byly vybrány
  foreach (string file in filenames)
  {
    // Třída ZipEntry představuje soubor, jež má být zazipován
    ZipEntry entry = new ZipEntry(Path.GetFileName(file));
    entry.DateTime = DateTime.Now;
    // Vloží soubor, jež bude komprimován, do kolekce
    s.PutNextEntry(entry);
    FileStream fs = File.OpenRead(file);
    int sourceBytes;
    do
    {
      // Načte bajty aktuálního souboru
      sourceBytes = fs.Read(buffer, 0, buffer.Length);
      // zapíše zkomprimované bajty do zip souboru 
      s.Write(buffer, 0, sourceBytes);
    } while (sourceBytes > 0);
  }
  s.Finish();
  // Ukončí datový proud k vytvářenému zip souboru
  s.Close();
}

Extrakce souborů

Extrahování souborů je jednodušší než jejich komprimace – poslouží nám k tomu třída FastZip, pomocí jejíž vlastnosti Password můžeme nastavit heslo archivu. K extrakci slouží metoda ExtractZip třídy FastZip, která jako první argument očekává název *.zip souboru a jako druhý argument cílovou složku, kam by měl být soubor rozbalen. Poslední argument slouží k definici názvů souborů, jež by neměly být extrahovány. Jelikož chceme extrahovat všechny soubory, dosadíme prázdný řetězec.

// Třída FastZip slouží k rychlé práci se zip soubory
FastZip z = new FastZip();
// nastaví heslo
z.Password = textBox3.Text;
// Extrahuje soubory
z.ExtractZip(this.textBox1.Text, this.textBox2.Text, "");

Knihovna #ZipLib si vedle tradičního formátu Zip poradí ještě převážně s linuxovými balíky GZip, BZip2 a Tar. Knihovna je distribuována pod licencí GPL, k dispozici je tedy jak sestavená DLL knihovna pro .NET Framework, tak zdrojové kódy v C#.

zipper.png  zipper.png
Zipper samozřejmě umí rozbalovat i zašifrovaný Zip balík. Pokud zadáte špatné heslo, komprimační knihovna vyhodí vyjímku, kterou si můžete ve zdrojovém kódu snadno ošetřit a spravovat dle libosti

Na závěr opět nabízíme stažení kompletního zdrojového kódu jako projektu pro bezplatné vývojové prostředí Microsoft Visual C# 2008 Express Edition, a pokud programovacímu jazyku C# nevládnete, můžete si jednoduchý kompresní program rovnou vyzkoušet, přeložili jsme ho totiž do běžné EXE aplikace pro Windows a připojili potřebnou kompresní knihovnu.

Kompresní knihovnu pro projekt najdete v adresáři bin/Debug a vzhledem k jiné absolutní cestě si ji budete muset znovu do projektu nastavit podle návodu v úvodu článku.

Diskuze (25) Další článek: Maximální Maxthon: výběr nejlepších doplňků

Témata článku: , , , , , , , , , , , , , ,