Zipping og zipping i Java

1. Oversikt

I denne raske opplæringen vil vi diskutere hvordan du kan pakke en fil inn i et arkiv og hvordan du pakker ut arkivet - alt ved hjelp av kjernebiblioteker levert av Java.

Disse kjernebibliotekene er en del av java.util.zip pakke - der vi kan finne alle tilknyttede verktøy for glidelås og utpakking.

2. Pakk en fil

La oss først se på en enkel operasjon - zippe en enkelt fil.

For vårt eksempel her vil vi zip en fil med navnet test1.txt inn i et arkivert navn compressed.zip.

Vi får selvfølgelig først tilgang til filen fra disk - la oss ta en titt:

offentlig klasse ZipFile {public static void main (String [] args) kaster IOException {String sourceFile = "test1.txt"; FileOutputStream fos = ny FileOutputStream ("compressed.zip"); ZipOutputStream zipOut = ny ZipOutputStream (fos); File fileToZip = ny fil (sourceFile); FileInputStream fis = ny FileInputStream (fileToZip); ZipEntry zipEntry = ny ZipEntry (fileToZip.getName ()); zipOut.putNextEntry (zipEntry); byte [] byte = ny byte [1024]; int lengde; mens ((lengde = fis.lesning (byte))> = 0) {zipOut.write (bytes, 0, lengde); } zipOut.close (); fis.close (); fos.close (); }}

3. Zip flere filer

Deretter, la oss se hvordan du zip flere filer i en zip-fil. Vi komprimerer test1.txt og test2.txt inn i multiCompressed.zip:

public class ZipMultipleFiles {public static void main (String [] args) kaster IOException {List srcFiles = Arrays.asList ("test1.txt", "test2.txt"); FileOutputStream fos = ny FileOutputStream ("multiCompressed.zip"); ZipOutputStream zipOut = ny ZipOutputStream (fos); for (String srcFile: srcFiles) {File fileToZip = ny fil (srcFile); FileInputStream fis = ny FileInputStream (fileToZip); ZipEntry zipEntry = ny ZipEntry (fileToZip.getName ()); zipOut.putNextEntry (zipEntry); byte [] byte = ny byte [1024]; int lengde; mens ((lengde = fis.lesning (byte))> = 0) {zipOut.write (bytes, 0, lengde); } fis.close (); } zipOut.close (); fos.close (); }}

4. Zip en katalog

La oss nå diskutere hvordan du zip en hel katalog. Vi vil katalogisere zipTest inn i dirCompressed.zip :

offentlig klasse ZipDirectory {public static void main (String [] args) kaster IOException {String sourceFile = "zipTest"; FileOutputStream fos = ny FileOutputStream ("dirCompressed.zip"); ZipOutputStream zipOut = ny ZipOutputStream (fos); File fileToZip = ny fil (sourceFile); zipFile (fileToZip, fileToZip.getName (), zipOut); zipOut.close (); fos.close (); } privat statisk ugyldig zipFile (File fileToZip, String fileName, ZipOutputStream zipOut) kaster IOException {if (fileToZip.isHidden ()) {return; } if (fileToZip.isDirectory ()) {if (fileName.endsWith ("/")) {zipOut.putNextEntry (new ZipEntry (fileName)); zipOut.closeEntry (); } annet {zipOut.putNextEntry (ny ZipEntry (filnavn + "/")); zipOut.closeEntry (); } Fil [] barn = fileToZip.listFiles (); for (File childFile: children) {zipFile (childFile, fileName + "/" + childFile.getName (), zipOut); } komme tilbake; } FileInputStream fis = ny FileInputStream (fileToZip); ZipEntry zipEntry = ny ZipEntry (filnavn); zipOut.putNextEntry (zipEntry); byte [] byte = ny byte [1024]; int lengde; mens ((lengde = fis.lesning (byte))> = 0) {zipOut.write (bytes, 0, lengde); } fis.close (); }}

Noter det:

  • For å zip underkataloger, gjentar vi dem rekursivt.
  • Hver gang vi finner en katalog, legger vi navnet til etterkommerne ZipEntry navn for å lagre hierarkiet.
  • Vi oppretter også en katalogoppføring for hver tomme katalog

5. Pakk ut et arkiv

La oss nå pakke ut et arkiv og trekke ut innholdet.

For dette eksemplet pakker vi ut compressed.zip inn i en ny mappe med navnet pakke ut.

La oss se:

offentlig klasse UnzipFile {public static void main (String [] args) kaster IOException {String fileZip = "src / main / resources / unzipTest / compressed.zip"; File destDir = new File ("src / main / resources / unzipTest"); byte [] buffer = ny byte [1024]; ZipInputStream zis = ny ZipInputStream (ny FileInputStream (fileZip)); ZipEntry zipEntry = zis.getNextEntry (); mens (zipEntry! = null) {// ...} zis.closeEntry (); zis.close (); }}

Inne i samtidig som Løkke, vi vil gjenta gjennom hver ZipEntry og sjekk først om det er en katalog. Hvis det er det, lager vi katalogen ved hjelp av mkdirs () metode; Ellers fortsetter vi med å lage filen:

while (zipEntry! = null) {File newFile = newFile (destDir, zipEntry); if (zipEntry.isDirectory ()) {if (! newFile.isDirectory () &&! newFile.mkdirs ()) {throw new IOException ("Kunne ikke opprette katalog" + newFile); }} annet {// fix for Windows-opprettet arkiv File parent = newFile.getParentFile (); if (! parent.isDirectory () &&! parent.mkdirs ()) {throw new IOException ("Kunne ikke opprette katalog" + foreldre); } // skriv filinnhold FileOutputStream fos = nytt FileOutputStream (newFile); int len; mens ((len = zis.read (buffer))> 0) {fos.write (buffer, 0, len); } fos.close (); } zipEntry = zis.getNextEntry (); }

En merknad her er at på ellers gren, sjekker vi også først om foreldrekatalogen til filen eksisterer. Dette er nødvendig for arkiver opprettet på Windows, der rotkatalogene ikke har en tilsvarende oppføring i zip-filen.

Et annet sentralt punkt kan sees i newFile () metode:

offentlig statisk fil newFile (File destinationDir, ZipEntry zipEntry) kaster IOException {File destFile = new File (destinationDir, zipEntry.getName ()); Streng destDirPath = destinasjonDir.getCanonicalPath (); Streng destFilePath = destFile.getCanonicalPath (); hvis (! destFilePath.startsWith (destDirPath + File.separator)) {kast ny IOException ("Oppføring er utenfor mål dir:" + zipEntry.getName ()); } return destFile; }

Denne metoden beskytter mot å skrive filer til filsystemet utenfor målmappen. Denne sårbarheten kalles Zip Slip, og du kan lese mer om den her.

6. Konklusjon

Denne opplæringen illustrerte hvordan vi kan bruke Java-biblioteker til å drifte og pakke ut filer.

Implementeringen av disse eksemplene finner du på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found