ZIP dosyaları ile ilgili güzel şey, sıralı yapısıdır: Her girdi bağımsız bir bayttır ve sonunda, tüm girişleri ve bunların ofsetlerini dosyada listeleyen bir Merkezi Dizin Dizini dir.
Kötü olan şey, java.util.zip. *
sınıfları bu endeksi göz ardı eder ve sadece dosyayı okumaya başlar ve ilk girdinin bir Yerel Dosya Başlığı bloğu olmasını bekler. Kendiliğinden açılan ZIP arşivleri için durum böyle değildir (bunlar EXE bölümü ile başlar).
Birkaç yıl önce, bu girişlerin dosyada nerede olduğunu bulmak için CDI'ya dayanan bireysel ZIP girişlerini (LFH + verileri) ayıklamak için özel bir ZIP ayrıştırıcısı yazdım. Ben sadece kontrol ettim ve aslında kendinden uzak bir ZIP arşivinin girişlerini daha fazla ado olmadan listeleyebilir ve size ofsetleri verebilir.
use that code to find the first LFH after the EXE part, and copy everything after that offset to a different File
, then feed that new File
to java.util.zip.ZipFile
:
Edit: Just skipping the EXE part doesn't seem to work, ZipFile
still won't read it and my native ZIP program complains that the new ZIP file is damaged and exactly the number of bytes I skipped are given as "missing" (so it actually reads the CDI). I guess some headers would need to be rewritten, so the second approach given below looks more promising -- or
- use that code for the full ZIP extraction (it's similar to
java.util.zip
); this would require some additional plumbing because the code originally wasn't intended as replacement ZIP library but had a very specific use case (differential updating of ZIP files over HTTP)
Kod, SourceForge'da ( proje sayfası , web sitesi ) ve Apache Lisansı 2.0 kapsamında lisanslıdır, dolayısıyla ticari kullanım iyi - AFAIK, oyun varlıklarını güncelleyen bir ticari oyun.
The interesting parts to get the offsets from a ZIP file are in Indexer.parseZipFile
which returns a LinkedHashMap
(so the first map entry has the lowest offset in the file). Here's the code I used to list the entries of a self-extracting ZIP archive (created with the WinZIP SE creator with Wine on Ubuntu from an acra release file):
public static void main(String[] args) throws Exception {
File archive = new File("/home/phil/downloads", "acra-4.2.3.exe");
Map resources = parseZipFile(archive);
for (Entry resource : resources.entrySet()) {
System.out.println(resource.getKey() + ": " + resource.getValue());
}
}
Muhtemelen kodun çoğunu, tüm başlık ayrıştırma sınıflarını içeren Dizinleyici
sınıfı ve zip
paketi dışında kopyalayabilirsiniz.