Tech Life

Ilustrační obrázek

Trampoty s rozbalováním zipu v Javě

07. 11. 2008 00:00    kategorie: Tech Life    autor: TZa    komentářů: 0

Chtěl bych se podělit o několik zajímavých zkušeností s rozbalováním zipu, na které jsem narazil při importech na jednom našem projektu. Nedílnou součástí importů je rozbalení příchozí dávky ve formátu zip. Jak se sluší, snažil jsem se pro takové věci použít samozřejmě Javu a asi to nikomu nebude divné, když máme package java.util.zip.
 

Jak Pat a Mat rozbalovali zip v Javě

Představme si to asi tak, že pro rozbalení zadaného zipu do zadaného adresáře použil Pat následující metodu (metoda unzipDirectoryZipEntry se stará o zachování adresářové struktury, metoda copyStream provádí kopírování vstupního streamu na výstupní přes buffer zadané délky, pro tento problém nejsou zajímavé):

Jednou přišel za Patem Mat a řekl mu, podívej, mám tu zip s 1 xml a 39 jpg soubory a ten cyklus projede jen 1x a pak už je zin.getNextEntry() null. Přeskočme vyprávění o cestách, které nevedly k cíli, tj. jak se Mat ptal kolegů, googlu, a hledal různé free alternativy k java.util.zip. Mat totiž nakonec objevil trochu jiný způsob s použitím třídy ZipFile a podle toho napsal vlastní metodu:

Matovi se jeho soubor rozbalil dobře, ale smůla, Matův kód začal házet výjimku hned zkraje při vybalování Patových souborů. Vzhledem k tomu, že se jedná o problém způsobený pravděpodobně dílčími verzemi zipu, které nelze ovlivnit, neboť jsou získávány z různých zdrojů, a vzhledem k termínu, shodli se Pat s Matem nakonec na řešení

I Mistr Jan Hus chce rozbalovat zipy

Výše uvedené řešení fungovalo do doby, než někdo poslal zip s diakritikou v názvu zabalených souborů. Algoritmus v metodě Pata skončí výjimkou, v metodě Mata vrátí zin == null a je nutno to na místě označeném “!!!” ošetřit.

Bohužel jsme zjistili, že je to problém java.util.zip. Jako další alternativa byla na takové případy nasazena knihovna Apache zip.

Dáreček, který nelze rozbalit

Další vypečená vlastnost java.util.zip je, že pokud přijde šikovně poškozený soubor, střeva knihovny vyhodí na nebohého programátora chybu java.lang.InternalError a nikoli potomka Exception, jak by se slušelo. (Pravděpodobným důvodem bylo asi to, že se zip používá na vybalení jaru a poškozený jar by opravdu znamenal interní chybu aplikace, nicméně uznávám, že v tomto vysvětlení je několik logických kotrmelců. Je to reportováno jako chyba (viz bug_id=4977607 a bug_id=4615343 a někde jsem myslím četl, že to Sun nebude fixovat na potomka Exception, ale pouze na speciálního potomka InternalError, aby byla zachována zpětná kompatibilita.) Kódem, který chytá Exception, tedy toto projde, což může mít neblahé následky na klienta.

Závěr

Veřejná metoda byla modifikována takto:

Uznávám, že to není zcela čisté - porušuje to zásadu: “Nepoužívejte výjimky k řízení toku programu.” a spoléhá na věci, které se mohou změnit např. při přechodu na vyšší Javu. Možná je řešení i příliš redundantní z hlediska použitých metod, nezkoumali jsme, zda by první dvě např. nebyly plně nahraditelné Apachem. Nicméně na obhajobu je třeba říci: 1. funguje to, 2. řešení máme pokryto unit testy (v současnosti máme v CVS uloženo 13 nejrůznějších zip souborů, které byly v průběhu času posbírány jako problematické).

Také doporučuji pozornosti knihovnu TrueZip, kterou jsem během experimentů zkoušel a na které mne zaujal přístup, kdy zip soubor se tváří jako adresář (je to tak modelováno i na úrovni objektového návrhu, připomíná to design pattern COMPOSITE).

Sdílet odkaz:
tisk

Diskuze k článku

K článku nebyl zatím přidán komentář.

Přidat příspěvek

 

Kontakt pro média


Máte zájem o další informace, odborný článek či přednášku na konferenci? Kontaktujte nás prosím na pr@etnetera.cz.

RSS - Tech life


RSS kanál Tech Life Blogu

Offlineblog

Offlineblog

Ljama


Komix z prostředí imaginární firmy.

ljama

Ještě jste ho nečetli? Tak tudy ...

 
Doporučujeme: Nabídka práce, volná pracovní místa - pracovní portál SPRÁVNÝKROK.CZ