Create a directory set of files to multiple zips? - java

I want to convert my directory(i.e. too large) which i want to convert to multiple zip files . Right now i can able to convert all files in the dirctory to one zip file using the below code .
package bulkimport;
import java.io.*;
import java.util.zip.*;
public class Tzip {
static final int BUFFER = 2048;
public static void main (String argv[]) {
try {
BufferedInputStream origin = null;
FileOutputStream dest = new
FileOutputStream("D:/abc/file.zip");
ZipOutputStream out = new ZipOutputStream(new
BufferedOutputStream(dest));
//out.setMethod(ZipOutputStream.DEFLATED);
byte data[] = new byte[BUFFER];
// get a list of files from current directory
File f = new File("D://current//");
String files[] = f.list();
for (int i=0; i<files.length; i++) {
System.out.println("Adding: "+files[i]);
FileInputStream fi = new
FileInputStream("D://current//"+files[i]);
origin = new
BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(files[i]);
out.putNextEntry(entry);
int count;
while((count = origin.read(data, 0,
BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
out.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
What i need to do to above code in such a way that it will create multiple zip files based on our condition(i.e.By setting threshold as 50MB it will create multiple zip files of each file having 50MB of compressed data )
Any help is appreciated
Thanks

Related

Extracting SFX 7-Zip

I want to extract two specific files from a .zip file. I tried the following library:
ZipFile zipFile = new ZipFile("myZip.zip");
Result:
Exception in thread "main" java.util.zip.ZipException: error in opening zip file
I also tried:
public void extract(String targetFileName) throws IOException
{
OutputStream outputStream = new FileOutputStream("targetFile.foo");
FileInputStream fileInputStream = new FileInputStream("myZip.zip");
ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(fileInputStream));
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null)
{
if (zipEntry.getName().equals("targetFile.foo"))
{
byte[] buffer = new byte[8192];
int length;
while ((length = zipInputStream.read(buffer)) != -1)
{
outputStream.write(buffer, 0, length);
}
outputStream.close();
break;
}
}
}
Result:
No exception, but an empty targetFile.foo file.
Note that the .zip file is of type SFX 7-zip and initially had the .exe extensions so that may be the reason for the failure.
As in Comments, Extracting SFX 7-Zip file is basically not supported with your library. But you can do with commons compress and xz Libary together with a quick "hack":
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
protected File un7zSFXFile(File file, String password)
{
SevenZFile sevenZFile = null;
File tempFile = new File("/tmp/" + file.getName() + ".temp");
try
{
FileInputStream in = new FileInputStream(file);
/**
* Yes this is Voodoo Code:
* first 205824 Bytes get skipped as these is are basically the 7z-sfx-runnable.dll
* common-compress does fail if this information is not cut away
* ATTENTION: the amount of bytes may vary depending of the 7z Version used!
*/
in.skip(205824);
// EndOfVoodoCode
tempFile.getParentFile().mkdirs();
tempFile.createNewFile();
FileOutputStream temp = new FileOutputStream(tempFile);
byte[] buffer = new byte[1024];
int length;
while((length = in.read(buffer)) > 0)
{
temp.write(buffer, 0, length);
}
temp.close();
in.close();
LOGGER.info("prepared exefile for un7zing");
if (password!=null) {
sevenZFile = new SevenZFile(tempFile, password.toCharArray());
} else {
sevenZFile = new SevenZFile(tempFile);
}
SevenZArchiveEntry entry;
boolean first = true;// accept only files with
while((entry = sevenZFile.getNextEntry()))
{
if(entry.isDirectory())
{
continue;
}
File curfile = new File(file.getParentFile(), entry.getName());
File parent = curfile.getParentFile();
if(!parent.exists())
{
parent.mkdirs();
}
FileOutputStream out = new FileOutputStream(curfile);
byte[] content = new byte[(int) entry.getSize()];
sevenZFile.read(content, 0, content.length);
out.write(content);
out.close();
}
}
catch(Exception e)
{
throw e;
}
finally
{
try
{
tempFile.delete();
sevenZFile.close();
}
catch(Exception e)
{
LOGGER.trace("error on cloasing Stream: " + sevenZFile.getDefaultName(), e);
}
}
}
Please acknowledge that this simple solution does only unpack in to the same directory as the as sfx-file is placed!

java.util.zip.ZipOutputStream - Zipping large files faster?

I am wondering how could I speed up the zipping process of 40+ image files, in my android app.
Clients are sending images, which needs to be compressed or placed into a folder before uploading on the server. Now I use the bellow method, but this way files are zipped in about 20-30 seconds, while the phone appears to be frozen and users tend to exit the app :(
The method I use for zipping:
private static final int BUFFER_SIZE = 2048;
public void zip(String[] files, String zipFile) throws IOException {
File zipDirectory = new File(Environment.getExternalStorageDirectory()
+ "/laborator/");
if (!zipDirectory.exists()) {
zipDirectory.mkdirs();
} else {
System.out.println("folder already exists!");
}
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
new FileOutputStream(Environment.getExternalStorageDirectory()
+ "/laborator/" + zipFile)));
try {
byte data[] = new byte[BUFFER_SIZE];
for (int i = 0; i < files.length; i++) {
FileInputStream fi = new FileInputStream(files[i]);
origin = new BufferedInputStream(fi, BUFFER_SIZE);
try {
ZipEntry entry = new ZipEntry(files[i].substring(files[i]
.lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
} finally {
origin.close();
}
}
} finally {
out.close();
System.out.println("ziping done");
sendZip();
}
}
Since your images are jpgs chances are high that you don't get any decent compression within the ZIP file. So you could try to just put the images uncompressed into the ZIP file which should be considerable faster without increasing the size of the ZIP file:
ZipEntry entry = new ZipEntry(files[i].subs...
entry.setMethod(ZipEntry.STORED);
out.putNextEntry(entry);
You could use
out.setLevel(Deflater.NO_COMPRESSION);
This way no need to change ZipEntry.

How to get .png files alone from one folder

Actually, i'm trying to zip all the files from one folder & .png files from another folder. I can able to get all the files from one folder. But i can't able to get the .png files from another folder in java. Is there any way ?
Code:
public class Zip {
public static void zip(String filepath,String reportFileName){
try {
File inFolder=new File(filepath);
File inFolder1=new File("../Agent_Portal_Auto_Testing/ReportCharts");
File outFolder=new File(reportFileName);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFolder)));
BufferedInputStream in = null;
byte[] data = new byte[1000];
String files[] = inFolder.list();
String files1[]=inFolder1.list();
for (int i=0; i<files.length; i++) {
in = new BufferedInputStream(new FileInputStream
(inFolder.getPath() + "/" + files[i]), 1000);
out.putNextEntry(new ZipEntry(files[i]));
int count;
while((count = in.read(data,0,1000)) != -1) {
out.write(data, 0, count);
}
}
for (int i=0; i<files1.length; i++) {
in = new BufferedInputStream(new FileInputStream
(inFolder1.getPath() + "/" + files1[i]), 1000);
out.putNextEntry(new ZipEntry(files1[i]));
int count;
while((count = in.read(data,0,1000)) != -1) {
out.write(data, 0, count);
}
}
out.closeEntry();
out.flush();
out.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
In the above code, i'm getting all the files from ReportCharts folder. But i need to get only the .png files.
See http://docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles(java.io.FileFilter)
You can use the file filter to filter out only the PNG files
http://docs.oracle.com/javase/7/docs/api/java/io/FileFilter.html
File [] pngFiles = directory.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isFile() && file.getName().toLowerCase().endsWith(".png");
}
});
you can add verify if you file is a .png one with :
if (files1[i].contains(".png"))
in your for loop.

How do you uncompress a split volume zip in Java?

I need to reassemble a 100-part zip file and extract the content. I tried simply concatenating the zip volumes together in an input stream but that does not work. Any suggestions would be appreciated.
Thanks.
Here is the code you can start from. It extracts a single file entry from the multivolume zip archive:
package org.test.zip;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.SequenceInputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class Main {
public static void main(String[] args) throws IOException {
ZipInputStream is = new ZipInputStream(new SequenceInputStream(Collections.enumeration(
Arrays.asList(new FileInputStream("test.zip.001"), new FileInputStream("test.zip.002"), new FileInputStream("test.zip.003")))));
try {
for(ZipEntry entry = null; (entry = is.getNextEntry()) != null; ) {
OutputStream os = new BufferedOutputStream(new FileOutputStream(entry.getName()));
try {
final int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
for(int readBytes = -1; (readBytes = is.read(buffer, 0, bufferSize)) > -1; ) {
os.write(buffer, 0, readBytes);
}
os.flush();
} finally {
os.close();
}
}
} finally {
is.close();
}
}
}
Just a note to make it more dynamic -- 100% based on mijer code below.
private void CombineFiles (String[] files) throws FileNotFoundException, IOException {
Vector<FileInputStream> v = new Vector<FileInputStream>(files.length);
for (int x = 0; x < files.length; x++)
v.add(new FileInputStream(inputDirectory + files[x]));
Enumeration<FileInputStream> e = v.elements();
SequenceInputStream sequenceInputStream = new SequenceInputStream(e);
ZipInputStream is = new ZipInputStream(sequenceInputStream);
try {
for (ZipEntry entry = null; (entry = is.getNextEntry()) != null;) {
OutputStream os = new BufferedOutputStream(new FileOutputStream(entry.getName()));
try {
final int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
for (int readBytes = -1; (readBytes = is.read(buffer, 0, bufferSize)) > -1;) {
os.write(buffer, 0, readBytes);
}
os.flush();
} finally {
os.close();
}
}
} finally {
is.close();
}
}
To just concatenate the segment data did not work for me. In this case the segments had been created with Linux command-line zip (InfoZip version 3.0):
> zip -s 5m data.zip -r data/
Segment files named data.z01, data.z02, ..., data.zip was created.
The first segment data.z01 contained the spanning signature 0x08074b50, as described in the Zip File Format Specification by PKWARE. The presence of these 4 bytes made Java ZipInputStream ignore all entries in the archive. The central registry in the last segment also contained extra segment information compared to a non-split archive but that did not cause ZipInputStream any problems.
All I had to do was to skip the spanning signature. The following code will extract entries both from an archive that have been segmented with zip -s and from a zip file that have been split by the Linux split commad, like this: split -d -b 5M data.zip data.zip.. The code is based on szhem's.
public class ZipCat {
private final static byte[] SPANNING_SIGNATURE = {0x50, 0x4b, 0x07, 0x08};
public static void main(String[] args) throws IOException {
List<InputStream> asList = new ArrayList<>();
byte[] buf4 = new byte[4];
PushbackInputStream pis = new PushbackInputStream(new FileInputStream(args[0]), buf4.length);
asList.add(pis);
if (pis.read(buf4) != buf4.length) {
throw new IOException(args[0] + " is too small for a zip file/segment");
}
if (!Arrays.equals(buf4, SPANNING_SIGNATURE)) {
pis.unread(buf4, 0, buf4.length);
}
for (int i = 1; i < args.length; i++) {
asList.add(new FileInputStream(args[i]));
}
try (ZipInputStream is = new ZipInputStream(new SequenceInputStream(Collections.enumeration(asList)))) {
for (ZipEntry entry = null; (entry = is.getNextEntry()) != null;) {
if (entry.isDirectory()) {
new File(entry.getName()).mkdirs();
} else {
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(entry.getName()))) {
byte[] buffer = new byte[1024];
int count = -1;
while ((count = is.read(buffer)) != -1) {
os.write(buffer, 0, count);
}
}
}
}
}
}
}

Issues with zipping files in Java

I am currently trying to zip all files within a directory.
The zip file is being created and the files are being processed - but for some reason the files are not appearing within the zip file.
The code being used to complete this task is as follows:
public class FileZipper {
public void zipDir( String dir, String zipFileName ) {
try{
File dirObj = new File(dir);
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
Logger.info("Creating : " + zipFileName);
addDir(dirObj, out);
out.close();
}
catch (Exception e){
Logger.error( e, "Error zipping directory" );
}
}
private void addDir(File dirObj, ZipOutputStream out) throws IOException {
File[] files;
if( !dirObj.isDirectory() ){
files = new File[] { dirObj };
}
else{
files = dirObj.listFiles();
}
byte[] tmpBuf = new byte[1024];
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
addDir(files[i], out);
continue;
}
FileInputStream in = new FileInputStream(files[i].getAbsolutePath());
Logger.info(" Adding: " + files[i].getAbsolutePath());
out.putNextEntry(new ZipEntry(files[i].getAbsolutePath()));
int len;
while ((len = in.read(tmpBuf)) > 0) {
out.write(tmpBuf, 0, len);
}
out.closeEntry();
in.close();
}
}
}
When reviewing the logging information, the files within the directories are being found and processed, but the created zip file contains no data.
Any help with this issues will be greatly appreciated.
Thanks
Apart from the fact that adding the file by its absolute path is probably not what you want, this code works just fine for me.
Hy,
Give a set of files name to this function, and a zip name.
It should work.
private void zipFiles (ArrayList<String> listWithFiles, String zipName) {
try {
byte[] buffer = new byte[1024];
// create object of FileOutputStream
FileOutputStream fout = new FileOutputStream(zipName);
// create object of ZipOutputStream from FileOutputStream
ZipOutputStream zout = new ZipOutputStream(fout);
for (String currentFile : listWithFiles) {
// create object of FileInputStream for source file
FileInputStream fin = new FileInputStream(currentFile);
// add files to ZIP
zout.putNextEntry(new ZipEntry(currentFile ));
// write file content
int length;
while ((length = fin.read(buffer)) > 0) {
zout.write(buffer, 0, length);
}
zout.closeEntry();
// close the InputStream
fin.close();
}
// close the ZipOutputStream
zout.close();
} catch (IOException ioe) {
System.out.println("IOException :" + ioe);
}
}
All good to you,
dAN

Categories