2009-11-27 12 views

Odpowiedz

21

Numer magic bytes dla formatu ZIP to 50 4B. Możesz przetestować strumień (używając mark i reset - możesz potrzebować do buffer), ale nie spodziewałbym się, że będzie to podejście w 100% niezawodne. Nie byłoby sposobu na odróżnienie go od pliku tekstowego zakodowanego w US-ASCII, który zaczynał się od liter PK.

Jednym ze sposobów uzyskania metadanych w formacie treści przed otwarciem strumienia byłoby odpowiednie przetworzenie.

5

Nie bardzo elegancki, ale niezawodne:

Jeśli strumień można odczytać poprzez ZipInputStream, to powinny być spakowane.

+1

To po prostu nie wydaje się miłe. Czy nie może to być uszkodzony strumień ZIP? – Fedearne

+10

@fedearne: Czy uszkodzony strumień zip jest strumieniem zip? – GvS

+2

Zgadzam się: jeśli ZipInputStream nie może go odczytać, nie ma to * znaczenia *, że "ma" być plikiem Zip. Dobrze? –

6

Można sprawdzić, że pierwsze cztery bajty strumienia są podpis lokalny nagłówek pliku który rozpoczyna nagłówek lokalnego pliku zachodzącej każdy plik w formacie ZIP, as shown in the spec here być 50 4B 03 04.

Trochę kodu testu pokazuje to działa:

byte[] buffer = new byte[4]; 

try { 
    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("so.zip")); 
    ZipEntry ze = new ZipEntry("HelloWorld.txt"); 
    zos.putNextEntry(ze); 
    zos.write("Hello world".getBytes()); 
    zos.close(); 

    FileInputStream is = new FileInputStream("so.zip"); 
    is.read(buffer); 
    is.close(); 
} 
catch(IOException e) { 
    e.printStackTrace(); 
} 

for (byte b : buffer) { 
    System.out.printf("%H ",b); 
} 

dał mi ten wynik:

50 4B 3 4 
+1

Miałem ten sam pomysł (chociaż zaufana Wikipedia ponad specyfikacją - wstyd!), Ale wygląda na to, że nie jest to niezawodny mechanizm: _ "Twórcy aplikacji powinni mieć świadomość, że można napotkać pliki ZIP z tymi deskryptorami danych oznaczania podpisów lub bez nich i powinien brać pod uwagę oba przypadki podczas czytania plików ZIP, aby zapewnić zgodność. "_ – McDowell

+1

To prawda z ogólnej perspektywy, ale domyślam się, że jeśli nie masz podpisu ZipInputStream zawiedzie, ponieważ nalega na obiekty ZipEntry. –

+1

Możesz mieć losowe śmieci dodawane do plików zip (takich jak pliki wykonywalne Microsoft Windows). Działają one tylko wtedy, gdy korzystasz z katalogu centralnego zamiast streamingu z lokalnymi nagłówkami. FWIW, Java PlugIn i WebStart korzystają z katalogu centralnego, ale teraz sprawdzają również pierwsze cztery bajty (patrz GIAR). –

35

Wprowadzenie

Ponieważ wszystkie odpowiedzi są 5 lat czuję się obowiązek spisać, co się dzisiaj dzieje. Poważnie wątpię, że należy czytać magiczne bajty strumienia! To kod niskiego poziomu, należy go ogólnie unikać.

Prosta odpowiedź

miku pisze:

Jeśli strumień można odczytać poprzez ZipInputStream należy spakowane.

Tak, ale w przypadku ZipInputStream „można przeczytać” oznacza, że ​​pierwsze wezwanie do .getNextEntry() zwraca niezerową wartość. Bez wyjątku łapanie et cetera. Więc zamiast magicznych bajtów parsowania można po prostu zrobić:

boolean isZipped = new ZipInputStream(yourInputStream).getNextEntry() != null; 

I to jest to!

ogólne rozpakować myśli

Ogólnie okazało się, że jest to o wiele bardziej wygodne do pracy z plikami podczas [un] skompresowanie, niż ze strumieni. Istnieje kilka przydatnych bibliotek, a ZipFile ma więcej funkcji niż ZipInputStream. Obsługa plików zip jest omówiona tutaj: What is a good Java library to zip/unzip files? Więc jeśli możesz pracować z plikami, lepiej!

przykładowy kod

potrzebowałem w mojej aplikacji do pracy z tylko strumieni. To jest ta metoda, którą napisałem do rozpakowania:

import org.apache.commons.io.IOUtils; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipInputStream; 

public boolean unzip(InputStream inputStream, File outputFolder) throws IOException { 

    ZipInputStream zis = new ZipInputStream(inputStream); 

    ZipEntry entry; 
    boolean isEmpty = true; 
    while ((entry = zis.getNextEntry()) != null) { 
     isEmpty = false; 
     File newFile = new File(outputFolder, entry.getName()); 
     if (newFile.getParentFile().mkdirs() && !entry.isDirectory()) { 
      FileOutputStream fos = new FileOutputStream(newFile); 
      IOUtils.copy(zis, fos); 
      IOUtils.closeQuietly(fos); 
     } 
    } 

    IOUtils.closeQuietly(zis); 
    return !isEmpty; 
} 
+1

Istnieją sytuacje, w których 'ZipOutputStream' nie jest poprawnie ukończony lub zamknięty, co oznacza, że ​​wynikowy plik wygeneruje' wyjątek IOEx', gdy zostanie sparsowany do 'nowego pliku ZipFile (f)', ponieważ jest niepoprawny. Powyższe nie zawiedzie, nawet jeśli plik zip jest nieprawidłowy do innych celów. –

0

Sprawdzanie magicznej liczby może nie być właściwą opcją.

plików DOCX mają również podobną liczbę magiczną 50 4B 3 4

+2

To dlatego, że pliki docx są plikami zip. – tak3shi

Powiązane problemy