Speed up extracting Zip-Files - java

I programmed a little example of working with zip-files in java. Actually I'm wondering, if there is a faster way to extract such a file. If i'm testing my tool with bigger files(Like 1GB or more) the process takes really to long.
I'm thankful for every advice.
Im doing it like this:
private void extractFolder(String zipFile, String extractFolder)
{
try
{
int BUFFER = 2048;
File file = new File(zipFile);
ZipFile zip = new ZipFile(file);
String newPath = extractFolder;
new File(newPath).mkdir();
Enumeration zipFiles = zip.entries();
while (zipFiles.hasMoreElements())
{
ZipEntry entry = (ZipEntry) zipFiles.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
// destFile = new File(newPath, destFile.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory())
{
BufferedInputStream inputSteam = new BufferedInputStream(zip.getInputStream(entry));
int currentByte;
// init buffer
byte data[] = new byte[BUFFER];
FileOutputStream outStream = new FileOutputStream(destFile);
BufferedOutputStream bufferedOutSteam = new BufferedOutputStream(outStream, BUFFER);
while ((currentByte = inputSteam.read(data, 0, BUFFER)) != -1)
{
bufferedOutSteam.write(data, 0, currentByte);
}
bufferedOutSteam.flush();
outStream.flush();
bufferedOutSteam.close();
inputSteam.close();
outStream.close();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}

Maybe that is not precisely the answer you are waiting for but you want to try this package; with the latest stable version your code can be "reduced" to this (note that the destination directory must not exist):
final Path zipFile = Paths.get("path/to/file.zip");
final Path dstDir = Paths.get("path/to/destination/directory");
try (
final FileSystem zipfs = MoreFileSystems.openZip(zipFile, true);
) {
MoreFiles.copyRecursize(zipfs.getPath("/"), dstDir,
RecursionMode.FAIL_FAST);
}
This will use the JRE's provided zip filesystem provider; it may or may not be optimized for your use case (I haven't checked!).
Javadoc links:
MoreFileSystems.openZip();
MoreFiles.copyRecursive()

Related

Split big zip file and combine it back as original zip file

I have a requirement to split a 100mb zip file(which will be having sub folders and images) into 10 zip files(each of 10mb).Then I need to send each sliced zip files to an API (as multipart reauest), in receiver API i need to combine each of the above 10 zip files back to origin 100mb zip file.
Below is the code for slicing
public static void splitZip(String zipName, String location, String NewZip) throws IOException{
FileInputStream fis = new FileInputStream(location);
ZipInputStream zipInputStream = new ZipInputStream(fis);
ZipEntry entry = null;
int currentChunkIndex = 0;
long entrySize = 0;
ZipFile zipFile = new ZipFile(location);
Enumeration enumeration = zipFile.entries();
String copDest = zipCopyDest + "\\" + NewZip + "_" + currentChunkIndex +".zip";
FileOutputStream fos = new FileOutputStream(new File(copDest));
BufferedOutputStream bos = new BufferedOutputStream(fos);
ZipOutputStream zos = new ZipOutputStream(bos);
long currentSize = 0;
try {
while ((entry = zipInputStream.getNextEntry()) != null && enumeration.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) enumeration.nextElement();
System.out.println(zipEntry.getName());
System.out.println(zipEntry.getSize());
entrySize = zipEntry.getSize();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if((currentSize + entrySize) > MAX_FILE_SIZE) {
zos.close();
currentChunkIndex++;
zos = getOutputStream(currentChunkIndex, NewZip);
currentSize = 0;
}else{
currentSize += entrySize;
zos.putNextEntry(new ZipEntry(entry.getName()));
byte[] buffer = new byte[8192];
int length = 0;
while ((length = zipInputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
byte[] unzippedFile = outputStream.toByteArray();
zos.write(unzippedFile);
unzippedFile = null;
outputStream.close();
zos.closeEntry();
}
}
} finally {
zos.close();
}
}
When i extract slices zips manually i found some images are corrupted am not able to open it. Also am not getting a proper solution for combining the zip files. Thanks in advance.
Zip specification has a feature to split zip files to any desired length (minimum split length should be 64kb). Zip4j, supports this feature to create split zip files (documentation). You can then pass each split file to the api. The api can then use the merge functionality in zip4j to merge those split files into a single zip file. On a side note: even without merging, it is a perfectly valid zip file. as long as all the split zip files are in the same directory.
The approach will not work if you have any file in the zip greater than 10 mb and also the else condition should be executed in both the cases and in this approach you have to depend on the size of file in zip may be better you go with approach of not creating smaller zips

Unpack all jar and war files with in a zip file

I have a zip file which contains,
war files
jar files
jar files may contain jar files within that.
I need to unzip a zip file which contains above-mentioned file types. Meanwhile, it should unpack all jar or war files also.
Is there any way to do this using shell script or java? else any single command to do all these.
Try below method:
public void unzipFile(String zipFile) throws ZipException, IOException
{
int BUFFER = 2048;
ZipFile zip = new ZipFile(new File(zipFile));
String pathToMainFile = zipFile.substring(0, zipFile.length() - 4);
new File(pathToMainFile).mkdir();
Enumeration zipEntries = zip.entries();
while (zipEntries.hasMoreElements())
{
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String current = entry.getName();
File dest = new File(pathToMainFile, current);
File outerParentSt = dest.getParentFile();
outerParentSt.mkdirs();
if (!entry.isDirectory())
{
BufferedInputStream is = new BufferedInputStream(zip.getInputStream(entry));
int currentByte;
byte data[] = new byte[BUFFER];
// write the file
FileOutputStream fos = new FileOutputStream(dest);
BufferedOutputStream destbuff = new BufferedOutputStream(fos,
BUFFER);
// r w to EOF
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
destbuff.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
fos.close;
}
if (current.endsWith(".zip")) //or jar or war
{
unzipFile(dest.getAbsolutePath()); //recursively
}
}
}

How to read a jar file, convert it to a string and create a new jar file from that string?

I´m trying to implement some "over the air" update mechanism for OSGi bundles. For that, I need to be able to create a jar file from a String (basically the content of the jar file read by JarInputStream). The following example code should illustrate my needs:
//read bundle to be copied!
File originalFile = new File(
"/Users/stefan/Documents/Projects/OSGi/SimpleBundle_1.0.0.201404.jar");
JarInputStream fis = new JarInputStream(new FileInputStream(originalFile));
StringBuilder stringBuilder = new StringBuilder();
int ch;
while ((ch = fis.read()) != -1) {
stringBuilder.append((char) ch);
}
fis.close();
//Create content string
String content = stringBuilder.toString();
if (logger.isInfoEnabled()) {
logger.info(content);
}
//Init new jar input stream
JarInputStream jarInputStream = new JarInputStream(
new ByteArrayInputStream(content.getBytes()));
if (logger.isInfoEnabled()) {
logger.info("Save content to disc!");
}
File newFile = new File(
"/Users/stefan/Documents/Projects/OSGi/equinox/SimpleBundle_1.0.0.201404.jar");
//Init new jar output stream
JarOutputStream fos = new JarOutputStream(
new FileOutputStream(newFile));
if (!newFile.exists()) {
newFile.createNewFile();
}
int BUFFER_SIZE = 10240;
byte buffer[] = new byte[BUFFER_SIZE];
while (true) {
int nRead = jarInputStream.read(buffer, 0,
buffer.length);
if (nRead <= 0)
break;
fos.write(buffer, 0, nRead);
}
//Write content to new jar file.
fos.flush();
fos.close();
jarInputStream.close();
Unfortunately, the created jar file is empty and throws an "Invalid input file" error if I try to open it with JD-GUI. Is it possible to create a jar file from the String "content"?
Best regards and thank you very much
Stefan
Your jar is empty because you do not read anything from the JarInputStream. If you want to read JarInputStream, you should iterate its entries. If you want to change the Manifest, the first entry should be skipped, use the getManifest() of the jarInputStream and the constructor of the JarOutputStream, where Manifest can be specified. Based on your code (no manifest change but plain jar copy):
ZipEntry zipEntry = jarInputStream.getNextEntry();
while (zipEntry != null) {
fos.putNextEntry(zipEntry);
// Simple stream copy comes here
int BUFFER_SIZE = 10240;
byte buffer[] = new byte[BUFFER_SIZE];
int l = jarInputStream.read(buffer);
while(l >= 0) {
fos.write(buffer, 0, l);
l = jarInputStream.read(buffer);
}
zipEntry = jarInputStream.getNextEntry();
}
You only need this if you want to change the content (Manifest or entries) of the JAR file during the copy. Otherwise, simple InputStream and FileOutputStream will do the work (as Tim said).

Java Connecting URL and downloading a zip but when extracting the zip it's not properly downloaded

I am sending a request XML to the URL and receiving a zip file to the given path.
Sometimes I'm facing troubles when the bandwidth is low this zip file, most likely 120MB size is not getting downloaded properly. And getting an error when extracting the zip file. Extracting happens from the code as well. When I download in high bandwidth this file gets download without issue.
I'm looking for a solution without making the bandwidth high, from program level are there any ways to download this zip file, may be part by part or something like that? Or anyother solution that you all are having is highly appreciated.
Downloading :
url = new URL(_URL);
sc = (HttpURLConnection) url.openConnection();
sc.setDoInput(true);
sc.setDoOutput(true);
sc.setRequestMethod("POST");
sc.connect();
OutputStream mOstr = sc.getOutputStream();
mOstr.write(request.getBytes());
InputStream in = sc.getInputStream();
FileOutputStream out = new FileOutputStream(path);
int count;
byte[] buffer = new byte[86384];
while ((count = in.read(buffer,0,buffer.length)) > 0)
out.write(buffer, 0, count);
out.close();
Extracting :
try {
ZipFile zipFile = new ZipFile(path+zFile);
Enumeration<?> enu = zipFile.entries();
while (enu.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) enu.nextElement();
String name = path+"/data_FILES/"+zipEntry.getName();
long size = zipEntry.getSize();
long compressedSize = zipEntry.getCompressedSize();
System.out.printf("name: %-20s | size: %6d | compressed size: %6d\n", name, size, compressedSize);
File file = new File(name);
if (name.endsWith("/")) {
file.mkdirs();
continue;
}
File parent = file.getParentFile();
if (parent != null) {
parent.mkdirs();
}
InputStream is = zipFile.getInputStream(zipEntry);
FileOutputStream fos = new FileOutputStream(file);
byte[] bytes = new byte[86384];
int length;
while ((length = is.read(bytes)) >= 0) {
fos.write(bytes, 0, length);
}
is.close();
fos.close();
}
zipFile.close();
} catch (Exception e) {
log("Error in extracting zip file ");
e.printStackTrace();
}

Unzipping the content of a file

I have an application where Service A will provide a zipped data to Service B. And service B needs to unzip it.
Service A has an exposes method getStream and it gives ByteArrayInputStream as output and the data init is zipped data.
However passing that to GzipInputStream gives Not in Gzip format exception.
InputStream ins = method.getInputStream();
GZIPInputStream gis = new GZIPInputStream(ins);
This gives an exception. When the file is dumped in Service A the data is zipped. So getInputStream gives the zipped data.
How to process it ans pass it to the GzipInputStream?
Regards
Dheeraj Joshi
If it zipped, then you must use ZipInputstream.
It does depend on the "zip" format. There are multiple formats that have the zip name (zip, gzip, bzip2, lzip) and different formats call for different parsers.
http://en.wikipedia.org/wiki/List_of_archive_formats
http://www.codeguru.com/java/tij/tij0115.shtml
http://docstore.mik.ua/orelly/java-ent/jnut/ch25_01.htm
If you are using zip then try this code:
public void doUnzip(InputStream is, String destinationDirectory) throws IOException {
int BUFFER = 2048;
// make destination folder
File unzipDestinationDirectory = new File(destinationDirectory);
unzipDestinationDirectory.mkdir();
ZipInputStream zis = new ZipInputStream(is);
// Process each entry
for (ZipEntry entry = zis.getNextEntry(); entry != null; entry = zis
.getNextEntry()) {
File destFile = new File(unzipDestinationDirectory, entry.getName());
// create the parent directory structure if needed
destFile.getParentFile().mkdirs();
try {
// extract file if not a directory
if (!entry.isDirectory()) {
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
// read and write until last byte is encountered
for (int bytesRead; (bytesRead = zis.read(data, 0, BUFFER)) != -1;) {
dest.write(data, 0, bytesRead);
}
dest.flush();
dest.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
is.close();
}
public static void main(String[] args) {
UnzipInputStream unzip = new UnzipInputStream();
try {
InputStream fis = new FileInputStream(new File("test.zip"));
unzip.doUnzip(fis, "output");
} catch (IOException e) {
e.printStackTrace();
}
}

Categories

Resources