👋 Nový obsah na borekb.cz

Info Tento blog je v "read-only módu" a nový obsah již nebude přibývat. O vývoji píšu na DevBlog.

Aplikace pro hledání duplicitních souborů

Server vbnet.cz v těchto dnech pořádá soutěž .NET Challenge 2008, a ačkoliv je můj vztah k Visual Basicu velmi vlažný (a to jsem ještě přehnal :), rozhodl jsem se se svými C# výtvory zúčastnit.

Úkolem prvního kola bylo vytvořit aplikaci pro vyhledávání duplicitních souborů a na můj výtvor se můžete podívat zde (pozor, jsou to zdrojáky, ne exáč).


Aplikace pro hledání duplicitních souborů

Z programátorského pohledu jsou na kódu zajímavé 2 věci – algoritmus samotný a pak jeho implementace pomocí návrhového vzoru Strategy.

Použitý algoritmus je velmi efektivní, protože každý soubor zpracovává pouze jednou (v kontrastu s naivní metodou, která by každý soubor porovnávala se všemi ostatními). Základní myšlenkou je, že dva soubory jsou stejné, pokud generují stejný hash (string o nějaké rozumné délce). Aplikace tedy funguje tak, že projde všechny soubory, pro každý spočítá hash, který si někam uloží, a na konci se jen podívá, které soubory vygenerovaly stejnou hodnotu – ty jsou vzájemně duplicitní.

V kódu je tento algoritmus implementován pomocí návrhového vzoru Strategy, což je ona druhá zajímavá věc. Strategy pattern je zhruba o tom, že kód sice definuje nějakou funkčnost, ale určité věci deleguje na jiné objekty. V případě této aplikace metoda findDuplicates() definuje obecný algoritmus pro vyhledávání duplicit (projdi soubory, pro každý spočítej hash a ten si ulož do tabulky), ale detaily generování hashe neimplementuje – to mají na starost třídy jako BinaryCompari­sonStrategy, CRCComparison­Strategy a podobně. Připadá mi to jako krásný use-case pro tento návrhový vzor.

Pokud se rozhodnete aplikaci kromě zkoumání jejího kódu třeba i používat (no, co kdyby :), neměli byste narazit na vážnější problémy – binární porovnání funguje i pro několika-gigabajtové soubory bez problémů s OutOfMemory­Exception (což byla vlastnost jedné z vývojových verzí :).

UI samozřejmě není dotažené (a ani není moc dobré – byl to můj první souboj s WPF), ale což, je to spíš ukázková aplikace než cokoliv jiného. Třeba se to někomu bude hodit aspoň jako ukázka reálné implementace návrhového vzoru Strategy.

Zařazeno do kategorií |
koubel (Pá, 2008-09-19 16:07):

strategy jak u učebnice, pěkné

Ondřej Štoček (So, 2008-09-20 16:15):

Hezké, ale nějak tam nevidím řešení kolizí (tzn. dva různé soubory mají stajný hash). Výskyt je sice nepravděpodobný, ale už z principu hashovací funkce možný.

Borek (So, 2008-09-20 19:33):

Předně je potřeba říct, že některé porovnávací strategie problém s kolizemi vůbec nemají – např. hash generovaný strategií FileNameAndSizeComparisonStrategy je vůči kolizím zcela imunní (z definice fungování oné strategie). Ale i u strategie používající binární porovnání a tedy hash SHA1 je pravděpodobnost kolizí tak malá, že jsem se rozhodl program kvůli tomu nekomplikovat. Jinak řečeno, je daleko pravděpodobnější, že aplikace nebude fungovat kvůli nějaké neošetřené výjimce nebo jiné programátorské chybě, než že by došlo ke kolizi v hashovacím algoritmu. Je ale asi chyba, že jsem se o tom nezmínil v dokumentaci (tedy já tam o tom původně měl jeden nebo dva odstavce, ale i ty jsem se v zájmu stručnosti rozhodl odstranit).

Jen tak pro zajímavost, navrhované řešení v jedné z vývojových verzí dokumentace bylo poměrně jednoduché – po skončení algoritmu by se soubory ve skupinách potenciálně duplicitních souborů porovnali každý s každým, čímž by se výměnou za drobné zhoršení výkonnosti jakékoliv kolize vyloučili. Po technické stránce by to znamenalo rozšířit rozhraní IFileComparisonStrategy o metodu CompareFiles(file1, file2) a nejspíš i o metodu IsFullComparisonNecessary, takže nic extra složitého. Algoritmus by zůstal velmi rychlý a stal by se 100% neprůstřelný (teď je jen 99.99999999999­999999% :)

Borek (Ne, 2008-09-21 11:58):

Poznámku o kolizích jsem do dokumentace znovu přidal.

Tom (Ne, 2008-11-09 17:32):

podarena ukazkova aplikace, kterou jsem chtel i prakticky vyuzit na uklid na 4 discich, ale je bohuzel nepouzitelna na porovnavani celych disku – pokud neni pristup do slozky napr System Volume Information tak aplikace konci :/

Borek B. (Ne, 2008-11-09 19:08):

Aplikace rozhodně nemá „produkční kvalitu“ a pár neošetřených výjimek by se tam určitě našlo. Určitě ale snadno najdeš freeware aplikace, které dělají to samé (a daleko víc) bez nějakých zásadních chyb.

Tomas Voracek (Út, 2008-12-30 21:59):

stejny program jsem delal jako zapoctak na PRG1(ZS 2007) na MFF a podobnost zdrojaku je neuveritelna :-)

Já (Út, 2009-02-10 17:03):

Vzhledem k tomu, že jsem se soutěže účastnil také a měl jsem možnost vidět ostatní řešení, tak toto je v porovnání s ostatními výtvory totální odpad. Když neberu v potaz naprosto odporné uživatelské rozhraní (ovšem v soutěži byly i horší), kód je neuvěřitelná prasárna, nejsou ošetřeny vyjímky a zbytečně je použito WPF, které se na tento typ aplikace vůbec nehodí (jeho možnosti zde nejsou využity ani minimálně).

Borek (Čt, 2009-02-12 10:26):

Uklidňuje mě jen to, že pokud nejsi Jarda Jirava nebo Petr Kurka, je tvůj kód ještě větší prasárna :) http://soutez­.vbnet.cz/Tas­k.aspx?id=2

Já (Čt, 2009-02-12 11:27):

BB: Tenhle komentář už začíná být trochu osobní, pošli kód a můžem se bavit dál.

Borek (Čt, 2009-02-12 10:24):

Pro anonyma, kterému mažu komentáře: napiš mi na b.bernard (at) cen­trum.cz, pokud mi něco chceš. Tvé komentáře v podobném stylu budou nadále mazány.

Komentáře jsou uzavřeny (blog je v read-only módu). Pokud mě chcete kontaktovat, můžete mailem.