Открыть zip файл java

How to unzip a zip file in Java

This article shows how to use ZipInputStream and zip4j library to unzip a zip file in Java.

To unzip a file manually, remember to add validation for the zip slip vulnerability.

 Path targetDirResolved = targetDir.resolve(zipEntry.getName()); // make sure normalized file still has targetDir as its prefix Path normalizePath = targetDirResolved.normalize(); if (!normalizePath.startsWith(targetDir)) < // may be zip slip, better stop and throws exception throw new IOException("Bad zip entry: " + zipEntry.getName()); >

1. Zip File

The following zip file structure is created by this article – create zip file in Java. Later we will show how to unzip it into a new folder.

1.1 A zip file contains only files.

 $ unzip -l test.zip Archive: test.zip Length Date Time Name --------- ---------- ----- ---- 0 2020-08-06 18:49 test-a2.log 0 2020-08-06 18:49 test-a1.log 14 2020-08-06 18:49 data/db.debug.conf 42 2020-08-06 18:49 README.md 32 2020-08-06 18:49 Test.java 0 2020-08-06 18:49 test-b/test-b1.txt 0 2020-08-06 18:49 test-b/test-c/test-c2.log 0 2020-08-06 18:49 test-b/test-c/test-c1.log 0 2020-08-06 18:49 test-b/test-b2.txt 0 2020-08-06 18:49 test-b/test-d/test-d2.log 0 2020-08-06 18:49 test-b/test-d/test-d1.log --------- ------- 88 11 files 

1.2 A zip file contains folders and files.

 $ unzip -l test.zip Archive: test.zip Length Date Time Name --------- ---------- ----- ---- 0 2020-07-27 15:10 test-a2.log 0 2020-07-23 14:55 test-a1.log 0 2020-08-06 18:57 data/ 14 2020-08-04 14:07 data/db.debug.conf 42 2020-08-05 19:04 README.md 32 2020-08-05 19:04 Test.java 0 2020-08-06 18:57 test-b/ 0 2020-07-24 15:49 test-b/test-b1.txt 0 2020-08-06 18:57 test-b/test-c/ 0 2020-07-27 15:11 test-b/test-c/test-c2.log 0 2020-07-27 15:11 test-b/test-c/test-c1.log 0 2020-07-27 15:10 test-b/test-b2.txt 0 2020-08-06 18:57 test-b/test-d/ 0 2020-07-27 15:11 test-b/test-d/test-d2.log 0 2020-07-27 15:11 test-b/test-d/test-d1.log --------- ------- 88 15 files 

2. Unzip file – ZipInputStream

To unzip a zip file, we use ZipInputStream to read the zip file, and copying files from the zip file into a new folder (outside zip file).

Читайте также:  Select java version windows

This below example unzip a zip file /home/mkyong/zip/test.zip into a folder /home/mkyong/zip/ , also provides a validation to prevent the zip slip vulnerability.

 package com.mkyong.io.howto; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class ZipFileUnZipExample < public static void main(String[] args) < Path source = Paths.get("/home/mkyong/zip/test.zip"); Path target = Paths.get("/home/mkyong/zip/"); try < unzipFolder(source, target); System.out.println("Done"); >catch (IOException e) < e.printStackTrace(); >> public static void unzipFolder(Path source, Path target) throws IOException < try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source.toFile()))) < // list files in zip ZipEntry zipEntry = zis.getNextEntry(); while (zipEntry != null) < boolean isDirectory = false; // example 1.1 // some zip stored files and folders separately // e.g data/ // data/folder/ // data/folder/file.txt if (zipEntry.getName().endsWith(File.separator)) < isDirectory = true; >Path newPath = zipSlipProtect(zipEntry, target); if (isDirectory) < Files.createDirectories(newPath); >else < // example 1.2 // some zip stored file path only, need create parent directories // e.g data/folder/file.txt if (newPath.getParent() != null) < if (Files.notExists(newPath.getParent())) < Files.createDirectories(newPath.getParent()); >> // copy files, nio Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING); // copy files, classic /*try (FileOutputStream fos = new FileOutputStream(newPath.toFile())) < byte[] buffer = new byte[1024]; int len; while ((len = zis.read(buffer)) >0) < fos.write(buffer, 0, len); >>*/ > zipEntry = zis.getNextEntry(); > zis.closeEntry(); > > // protect zip slip attack public static Path zipSlipProtect(ZipEntry zipEntry, Path targetDir) throws IOException < // test zip slip vulnerability // Path targetDirResolved = targetDir.resolve("../../" + zipEntry.getName()); Path targetDirResolved = targetDir.resolve(zipEntry.getName()); // make sure normalized file still has targetDir as its prefix // else throws exception Path normalizePath = targetDirResolved.normalize(); if (!normalizePath.startsWith(targetDir)) < throw new IOException("Bad zip entry: " + zipEntry.getName()); >return normalizePath; > > 
 $ pwd /home/mkyong/zip/ $ tree . ├── data │ └── db.debug.conf ├── README.md ├── test-a1.log ├── test-a2.log ├── test-b │ ├── test-b1.txt │ ├── test-b2.txt │ ├── test-c │ │ ├── test-c1.log │ │ └── test-c2.log │ └── test-d │ ├── test-d1.log │ └── test-d2.log ├── Test.java 

3. Unzip file – zip4j

This example uses the zip4j library to unzip a zip file.

  net.lingala.zip4j zip4j 2.6.1  
 // it takes `File` as arguments public static void unzipFolderZip4j(Path source, Path target) throws IOException

4. ZipException: invalid entry size

If we hit the following invalid entry size exception, it means the zip file is corrupted during the copy, transfer, or creation process. There is no way to fix a corrupted file size, get a new zip file again.

 java.util.zip.ZipException: invalid entry size (expected 0 but got 1282 bytes) at java.base/java.util.zip.ZipInputStream.readEnd(ZipInputStream.java:398) at java.base/java.util.zip.ZipInputStream.read(ZipInputStream.java:197) at java.base/java.io.FilterInputStream.read(FilterInputStream.java:107) at com.mkyong.io.howto.ZipFileUnZipExample.unzipFolder(ZipFileUnZipExample.java:63) at com.mkyong.io.howto.ZipFileUnZipExample.main(ZipFileUnZipExample.java:22) 

Download Source Code

References

mkyong

Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Thank you – very nice. This saved me tons of time (posted a small fix) below.

Nice, but what about a zip inside a zip?
I’ll need to call the method twice? ‘-‘

For embedded zip or zip inside a zip file, I’m not sure what is the general practice.

The code needs to be modified to support the embedded zip file.

if(zipEntry.getName().endsWith(«.zip»)) // unzip it again.
>

I haven’t tested the above idea, but it should work; if someone has time, please test it and comment here.

Hey man, you are awsome. actually this programm saves my time a lot and i change it a bit so that it can go to a directory and fild all zip files and unzip them. thanks again

I tried this code , It works perfectly with .zip files only. but not with .rar. It returns null. If I want extract data from .rar file so what to do?

Rar and Zip are two different things./ Why would you possibly think code for one would work for the other?

Hi, Do you know how can I decompress a .rar file?

Same can be achieved out of the box using Ant Compress library

 org.apache.ant ant-compress 1.2  
Unzip unzipper = new Unzip(); unzipper.setSrc(theZIPFile); unzipper.setDest(theTargetFolder); unzipper.execute();

Your site is simply wonderful. Small snippets so useful to use/understand as part of a bigger code. Appreciate it and do let me know if there is anyway I can contribute it to the site in anyway.

Not sure if this is the right place to post this but maybe it will help somebody.
Mine problem was that i had a zip inside of my runnable jar file that needed to be extracted . The zip had folders inside.
how to get the zip file from inside the jar:

InputStream stream; stream = this.getClass().getClassLoader().getSystemResourceAsStream("resources/Sounds.zip");

where the resources is the folder/package inside of the root of the jar
now is the rest of the code (a little modification of the original one)

package system; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class UnZip < ListfileList; UnZip(InputStream stream, File dest) < unZipIt(stream,dest); // the stream i got from the first part and dest as a file >/** * Unzip it * @param stream input zip file * @param output zip file output folder */ public void unZipIt(InputStream stream, File dest) < byte[] buffer = new byte[1024]; try< //create output directory is not exists File folder = dest; if(!folder.exists())< folder.mkdir(); >//get the zip file content ZipInputStream zis = new ZipInputStream(stream); //get the zipped file list entry ZipEntry ze = zis.getNextEntry(); while(ze!=null) < String fileName = ze.getName(); File newFile = new File(dest + File.separator + fileName); System.out.println("file unzip : "+ newFile.getAbsoluteFile()); //create all non exists folders //else you will hit FileNotFoundException for compressed folder if(ze.isDirectory()) < new File(newFile.getParent()).mkdirs(); >else < FileOutputStream fos = null; new File(newFile.getParent()).mkdirs(); fos = new FileOutputStream(newFile); int len; while ((len = zis.read(buffer)) >0) < fos.write(buffer, 0, len); >fos.close(); > ze = zis.getNextEntry(); > zis.closeEntry(); zis.close(); System.out.println("Done"); >catch(IOException ex) < ex.printStackTrace(); >> >

with this i was able to extract files and folders from the zip to a desired location.
Hope it can prevent some headToWall love

getResouceAsStream() is returning null, even though the zip file is present. Any idea why this happens?

I m also gettin the same error
getResourceAsStream() is returning null…
If got the solution please reply

Thanks a lot! I was happy that someone posted a solution to the same problem as I had. There should be more people like you. 🙂

I am having one password protected file, which is created using
PKZIP utility (http://www.pkware.com/software/pkzip)

My question how do i encrypt zip file if i don’t know which encryption Algorithm,
it’s using. I have the password.

let me know if any one is having any idea.

I’m getting the next Exception

java.util.zip.ZipException: only DEFLATED entries can have EXT descriptor

How to unzip a zip file in sftp server using java ?

It helped me a lot to know there is two kind of zip files (folder inline or separate). Thank you very much \o/

This code is insecure and vulnerable to the Zip Slip vulnerability.
https://snyk.io/research/zip-slip-vulnerability

We updated the article with zip slip validation, thanks for your feedback and zip slip article.

The sourcecode is wrong. No offense, just pointing out the mistake. On win8 when there’s folder inside zip file, the code looks for parent dir and do not asks if the current “file” is a dir, therefore the dir is created as “file” with 0 size and without any file suffix, and then the attempt to create now the parent folder – with the same name as the 0 size file – will fail and first attempt to actually unzip file into that folder throws an exception. Before calling the FileOutputStream, make sure the file is not a folder (dot in filename for example).

We updated the article with the latest example to unzip a file, and the above comment is irrelevant now.

How to unzip folder having file names with special characters for e.g. test.zip having file with name fndStaticLookups_finder=LookupTypeFinder%3BBindLookupType%3DACTIVITY_SHOWTIMEAS_CD.json

Hi mkyong
I have a zip file which contains multiple CSV files and some folders. These folders also contains CSV files.
In a word, I wonder how to deal with this kind of zip file recursively?

Did you run the above unzip example? It should work and unzip your file structure correctly.

private static final String INPUT_ZIP_FILE = “/classes/sds.zip”;
private static final String OUTPUT_FOLDER = “/classes/testdata/

java.io.FileNotFoundException: sds.zip (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.(FileInputStream.java:138)
at java.io.FileInputStream.(FileInputStream.java:93)
at com.test.zip.UnZip.unZipIt(UnZip.java:43)
at com.test.zip.UnZip.main(UnZip.java:19)

We updated the unzip example with directory checking.

if (zipEntry.getName().endsWith(File.separator)) isDirectory = true;
>

FileOutputStream fos = new FileOutputStream(newFile);

int len;
while ((len = zis.read(buffer)) > 0) fos.write(buffer, 0, len);
>

Wouldn’t a BufferedWriter probably be faster ? Just a thought. Thanks for the tuto.

I didn’t test the performance, and the Files.copy is the easiest way to copy a file. May be someone can feedback on this.

//— Here is a fix so that is creates when there are sub-directories .. this creates if needed
// Note: If you had run it before, remove the existing files because there may be a blank file holding the spot of the directory

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class FileUnzipper List fileList;

/*
* private static final String INPUT_ZIP_FILE = “C:\MyFile.zip”; private
* static final String OUTPUT_FOLDER = “C:\outputzip”;
*
* public static void main( String[] args ) < FileUnzipper unZip = new
* FileUnzipper(); unZip.unZipIt(INPUT_ZIP_FILE,OUTPUT_FOLDER); >
*
*/
/**
* Unzip it
*
* @param zipFile
* input zip file
* @param output
* zip file output folder
*/
public static boolean unZipIt(String zipFile, String outputFolder) boolean tmpRet = true;
byte[] buffer = new byte[1024];

// create output directory is not exists
File folder = new File(outputFolder);
if (!folder.exists()) folder.mkdir();
>

// get the zip file content
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
// get the zipped file list entry
ZipEntry ze = zis.getNextEntry();

String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator + fileName);

String tmpCheckFN = FilenameUtils.removeExtension(fileName);

if (tmpCheckFN.equalsIgnoreCase(fileName)) // — Directory, create if needed
if (!newFile.exists()) System.out.println(“Create dir ” + outputFolder + File.separator + fileName);
boolean success = newFile.mkdirs();
if (!success) System.err.println(“Could not create directory for ” + fileName + “.”);
return false;
>
>
> else System.out.println(“file unzip : ” + newFile.getAbsoluteFile());

FileOutputStream fos = new FileOutputStream(newFile);

int len;
while ((len = zis.read(buffer)) > 0) fos.write(buffer, 0, len);
>

> catch (IOException ex) tmpRet = false;
ex.printStackTrace();
>

Источник

Оцените статью