Qual è il modo migliore per scoprire i java.io.InputStream
contiene dati compressi?Il modo migliore per rilevare se un flusso è compresso in Java
risposta
Il magic bytes per il formato ZIP è 50 4B
. È possibile testare lo stream (utilizzando mark e reset - potrebbe essere necessario il numero buffer) ma non mi aspetto che questo sia un approccio affidabile al 100%. Non ci sarebbe modo di distinguerlo da un file di testo codificato US-ASCII iniziato con le lettere PK
.
Il migliore sarebbe fornire i metadati nel formato di contenuto prima di aprire lo stream e quindi trattarlo in modo appropriato.
Non molto elegante, ma affidabile:
se il flusso può essere letta tramite ZipInputStream
, occorre zip.
Si potrebbe verificare che i primi quattro byte del torrente sono la firma intestazione del file locale che avvia il file locale di intestazione che procede ogni file in un file ZIP, as shown in the spec here essere 50 4B 03 04
.
Un codice di prova piccoli spettacoli far funzionare tutto questo:
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);
}
mi ha dato questo output:
50 4B 3 4
Ho avuto la stessa idea (anche se Wikipedia di fiducia rispetto alle specifiche - per vergogna!), Ma sembra che questo non sia un meccanismo affidabile: _ "Gli implementatori devono essere consapevoli che i file ZIP possono essere incontrati con o senza questa firma e dovrebbe tenere conto di entrambi i casi durante la lettura di file ZIP per garantire la compatibilità. "_ – McDowell
Questo è vero per una prospettiva generale, ma suppongo che se non si ha la firma ZipInputStream avrà esito negativo come insiste sugli oggetti ZipEntry. –
È possibile inserire un file spazzatura casuale anteposto ai file zip (come gli eseguibili di Microsoft Windows). Funzionano solo se si utilizza la directory centrale anziché lo streaming con intestazioni locali. FWIW, Java PlugIn e WebStart utilizzano la directory centrale ma ora controllano anche i primi quattro byte (vedere i GIAR). –
Introduzione
Dal momento che tutte le risposte sono 5 anni mi sento un dovere di scrivere, cosa sta succedendo oggi. Dubito seriamente che si dovrebbero leggere i byte magici del flusso! Questo è un codice di basso livello, dovrebbe essere evitato in generale.
Risposta semplice
Miku scrive:
se il flusso può essere letta tramite ZipInputStream, deve essere compresso.
Sì, ma in caso di ZipInputStream
"si può leggere" significa che prima chiamata a .getNextEntry()
restituisce un valore non nullo. Nessuna eccezione che cattura eccetera. Così, invece di byte magici parsing solo si può fare:
boolean isZipped = new ZipInputStream(yourInputStream).getNextEntry() != null;
E il gioco è fatto!
generali pensieri di decompressione
In generale, è risultato che è molto più conveniente per lavorare con i file, mentre [un] zippare, che con i flussi. Ci sono diverse librerie utili, oltre a ZipFile ha più funzionalità di ZipInputStream. La gestione dei file zip è discussa qui: What is a good Java library to zip/unzip files? Quindi se si può lavorare con i file è meglio farlo!
Esempio di codice
ho bisogno nella mia richiesta di lavorare solo con i flussi. Quindi questo è il metodo che ho scritto per decomprimerlo:
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;
}
Ci sono situazioni in cui un 'ZipOutputStream' non è finito o chiuso correttamente che significherà che il file risultante genererà una' IOException' quando viene analizzata in un 'nuovo ZipFile (f)' perché non è valido. Quanto sopra non fallirà, anche quando il file zip non è valido per altri scopi. –
Controllare il numero magico potrebbe non essere l'opzione giusta.
I file Docx hanno anche un numero magico simile 50 4B 3 4
Ecco perché i file docx sono file zip. – tak3shi
- 1. Il modo migliore per rilevare se il codice è in esecuzione in un server delle applicazioni java
- 2. Qual è il modo migliore per rilevare se è disponibile un server proxy?
- 3. Qual è il modo migliore per rilevare il colore bianco?
- 4. Il modo migliore per rilevare IronPython
- 5. Qual è il modo migliore per rilevare l'eccezione nell'attività?
- 6. Il modo migliore per rilevare se il testo di TextView è stato modificato?
- 7. il modo migliore per rilevare il browser in js
- 8. Qual è il modo migliore per verificare se una stringa contiene un URL in Java/Android?
- 9. C'è un modo per rilevare un linguaggio RTL in Java?
- 10. C'è un modo per rilevare se un oggetto è bloccato?
- 11. Esiste un modo per rilevare se un'unità è un SSD?
- 12. Come verificare se un file è compresso in R
- 13. Il modo migliore per raccogliere il flusso Java-8 su Guava ImmutableList
- 14. Il modo migliore per creare un collage (in Java)
- 15. Il modo migliore per riorganizzare un ArrayList in Java
- 16. Qual è il modo migliore per aggregare gli stream in un DISTINCT con Java 8
- 17. OpenCV: Il modo migliore per rilevare gli angoli sulla scacchiera
- 18. modo migliore per testare se un tipo è una raccolta
- 19. Il modo migliore per verificare se una variabile è nulla?
- 20. Il modo migliore per sapere se JQuery è disponibile?
- 21. Il modo migliore per analizzare Java in Java
- 22. Qual è il modo migliore per eseguire codice Java sandboxed?
- 23. Qual è il modo migliore per verificare il flusso di lavoro in Spring-Batch?
- 24. Esiste un modo per riutilizzare un flusso in java 8?
- 25. Qual è il modo migliore per scrivere se/else se/else se/else in HIVE?
- 26. Qual è il modo migliore per rilevare le impostazioni locali di un browser nel 2012?
- 27. Il modo migliore per verificare se un file DLL è un assembly CLR in C#
- 28. Il modo più veloce per rilevare se un doppio è finito?
- 29. Il modo migliore per incrementare l'intero in arrayList in Java
- 30. È questo il modo migliore per riscrivere il contenuto di un file in Java?
Questa parte di una richiesta/risposta HTTP? –