So iam working on a project where i get to a point when i need to zip multiple folders (4folders to be specific) and one file in one output.zip file using java
So is there anyway for me to do it and by the way putting all the folders and file in one directory and then zipping it doesn't give the same result in other words the folders have to be in root level of the zip file
There are several solutions.
This one for example:
public static void zipDirectory(ZipOutputStream zos, File fileToZip, String parentDirectoryName) throws Exception
{
if (fileToZip == null || !fileToZip.exists())
{
return;
}
String zipEntryName = fileToZip.getName();
if (parentDirectoryName!=null && !parentDirectoryName.isEmpty())
{
zipEntryName = parentDirectoryName + "/" + fileToZip.getName();
}
// If we are dealing with a directory:
if (fileToZip.isDirectory())
{
System.out.println("+" + zipEntryName);
if(parentDirectoryName == null) // if parentDirectory is null, that means it's the first iteration of the recursion, so we do not include the first container folder
{
zipEntryName = "";
}
for (File file : fileToZip.listFiles()) // we iterate over all the folders/files and archive them by keeping the structure too.
{
zipDirectory(zos, file, zipEntryName);
}
} else // If we are dealing with a file, then we zip it directly
{
System.out.println(" " + zipEntryName);
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(fileToZip);
zos.putNextEntry(new ZipEntry(zipEntryName));
int length;
while ((length = fis.read(buffer)) > 0)
{
zos.write(buffer, 0, length);
}
zos.closeEntry();
fis.close();
}
}
then you could use this function like this:
try
{
File directoryToBeZipped = new File("C:\\New\\test");
FileOutputStream fos = new FileOutputStream("C:\\New\\test\\archive.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
zipDirectory(zos, directoryToBeZipped, null);
zos.flush();
fos.flush();
zos.close();
fos.close();
} catch (Exception e)
{
e.printStackTrace();
}
Or you could use the ZeroTurnAround ZIP Library. And do this in one line:
ZipUtil.pack(new File("D:\\sourceFolder\\"), new File("D:\\generatedZipFile.zip"));
Dead easy way (though you'll get warnings about proprietary classes)
final String[] ARGS = { "-cfM", "x.zip", "folder1", "folder2", "folder3", "folder4", "file.txt" };
sun.tools.jar.Main.main(ARGS);
It might be worth getting a similar thing that won't give you warnings
Related
My app is a tender document system where each tender number has one or more pdf files attached.
application is done in java ee using struts and mysql.
in a database table the paths of each related pdf file for a tender number is stores.
I want to get all the pdf files and create a single ZIP file for each tender number so that user can download that zip file and have all the related documents in a single click.
I tried Google and found something called ZipOutputStream but i cannot understand how to use this in my application.
You're almost there... This is a small example of how to use ZipOutputStream... let's asume that you have a JAVA helper H that returns database records with pdf file paths (and related info):
FileOutputStream zipFile = new FileOutputStream(new File("xxx.zip"));
ZipOutputStream output = new ZipOutputStream(zipFile);
for (Record r : h.getPdfRecords()) {
ZipEntry zipEntry = new ZipEntry(r.getPdfName());
output.putNextEntry(zipEntry);
FileInputStream pdfFile = new FileInputStream(new File(r.getPath()));
IOUtils.copy(pdfFile, output); // this method belongs to apache IO Commons lib!
pdfFile.close();
output.closeEntry();
}
output.finish();
output.close();
Checkout this code, here you can easily create a zip file directory:
public class CreateZipFileDirectory {
public static void main(String args[])
{
try
{
String zipFile = "C:/FileIO/zipdemo.zip";
String sourceDirectory = "C:/examples";
//create byte buffer
byte[] buffer = new byte[1024];
FileOutputStream fout = new FileOutputStream(zipFile);
ZipOutputStream zout = new ZipOutputStream(fout);
File dir = new File(sourceDirectory);
if(!dir.isDirectory())
{
System.out.println(sourceDirectory + " is not a directory");
}
else
{
File[] files = dir.listFiles();
for(int i=0; i < files.length ; i++)
{
System.out.println("Adding " + files[i].getName());
FileInputStream fin = new FileInputStream(files[i]);
zout.putNextEntry(new ZipEntry(files[i].getName()));
int length;
while((length = fin.read(buffer)) > 0)
{
zout.write(buffer, 0, length);
}
zout.closeEntry();
fin.close();
}
}
zout.close();
System.out.println("Zip file has been created!");
}
catch(IOException ioe)
{
System.out.println("IOException :" + ioe);
}
}
}
im using this code it perfectly create zip files for example i have folder
sdcard/music and when i create xxx.zip file it creates .zip file includes music/songs and also some sub folders in it
but i want to exclude "music" the main Folder in the .zip file and want it to start directly including all songs and subfolders in it,how to do it
i use this way but it takes main folder name as well when zipping
public void unzipbutton(View v){ // button click
try {
FileOutputStream fos = new FileOutputStream("/mnt/sdcard/songs.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
addDirToZipArchive(zos, new File("/mnt/sdcard/music"), null);
zos.flush();
fos.flush();
zos.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addDirToZipArchive(ZipOutputStream zos, File fileToZip, String parrentDirectoryName) throws Exception {
if (fileToZip == null || !fileToZip.exists()) {
return;
}
String zipEntryName = fileToZip.getName();
if (parrentDirectoryName!=null && !parrentDirectoryName.isEmpty()) {
zipEntryName = parrentDirectoryName + "/" + fileToZip.getName();
}
if (fileToZip.isDirectory()) {
System.out.println("+" + zipEntryName);
for (File file : fileToZip.listFiles()) {
addDirToZipArchive(zos, file, zipEntryName);
}
} else {
System.out.println(" " + zipEntryName);
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(fileToZip);
zos.putNextEntry(new ZipEntry(zipEntryName));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
fis.close();
}
}
anybody help on this,thanks
this has been so tricky till now no way works at the moments for me :/
In your ZipEntry check the full path of zipEntryName, it must be something like: "music/Pink/try.mp3" just invoke a substring in order to obtain as zipEntryName "Pink/try.mp3", your zip file will be the same "songs.zip" but inside of it you'll find the folder "Pink" instead the main folder "music/Pink..."
It worked for me.
i'm using the following code from the web
File dir = new File(dest.getAbsolutePath(), archiveName);
// create output directory if it doesn't exist
if (!dir.exists()) {
dir.mkdirs();
}
System.err.println(pArchivePath);
ZipFile zipFile = null;
try {
zipFile = new ZipFile(pArchivePath);
Enumeration<?> enu = zipFile.entries();
while (enu.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) enu.nextElement();
String name = 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("/")) {
System.err.println("make dir " + name);
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[1024];
int length;
while ((length = is.read(bytes)) >= 0) {
fos.write(bytes, 0, length);
}
is.close();
fos.close();
}
zipFile.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (zipFile != null) {
try {
zipFile.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
to unzip an archive. It's packed with 7zip or Winrar as an .zip archive but renamed to .qtz (but i don't thing this causes the problem..)
So if i run the code to unzip my archive everything works fine: i get the output on sysout/err listing all files and also no exception occurs, but if i look in the destination directory ... it's empty - just the root folder exists.
I also used
Runtime.getRuntime().exec(String.format("unzip %s -d %s", pArchivePath, dest.getPath()));
but I can't use this anymore 'cause a new process is started and I'm continuing working on the archive right after the unzip process in the java code.
Well the question is.. why doesn't this peace of code work? There a lot of similar examples but none of them worked for me.
br, Philipp
EDIT: The following solved my Problem
File file = new File(dir.getParent(), name);
So i didn't set the right parent path for this file.
The below fragment in your code:
File parent = file.getParentFile();
if (parent != null) {
parent.mkdirs();
}
where does this create the parent directories? Because I tried your code and it's not creating in the destination directory but rather in my Eclipse's project directory. Looking at your code, the destination directory is nowhere used, right?
The code actually extracts the contents of the zip file but not where I expected it.
I am thinking because I don't see you doing something like this:
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipPath+ "Zip.zip"));
out.putNextEntry(new ZipEntry("Results.csv"));
I am still working on it but I think that the problem because that makes the file inside of the zip
Also you should probably use the ZipOutputStream to write; like
out.write(bytes, 0, length);
I have this little piece of code
public void doBuild() throws IOException {
ZipEntry sourceEntry=new ZipEntry(sourcePath);
ZipEntry assetEntry=new ZipEntry(assetPath);
ZipOutputStream out = new ZipOutputStream(new FileOutputStream("output/"+workOn.getName().replaceAll(".bld"," ")+buildNR+".zip"));
out.putNextEntry(sourceEntry);
out.putNextEntry(assetEntry);
out.close();
System.err.println("Build success!");
increaseBuild();
}
So, if I run it it runs trough it fine, creates the .zip and all, but the zip file is empty. sourceEntry and assetEntry are both directories. How could I get those directories to my .zip easily?
For those interested this is a MC mod build system and can be found at https://bitbucket.org/makerimages/makerbuild-system NOTE: the code above is not commited or pushed to there yet!!!!!!!!
Try something like this. The parameter useFullFileNames specifies
whether you want to preserve the full names of the paths to the
files which you're about to zip.
So if you have two files
/dir1/dir2/a.txt
and
/dir1/b.txt
the useFullFileNames specifies if you want to finally see in
the zip file those original paths to the two files or just
the two files with no paths like this
a.txt
and
b.txt
in the root of the zip file which you create.
Note that in my example, the files which are zipped
are actually read and then written to out.
I think you're missing that part.
public static boolean createZip(String fNameZip, boolean useFullFileNames, String... fNames) throws Exception {
try {
int cntBufferSize = 256 * 1024;
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(fNameZip);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
byte bBuffer[] = new byte[cntBufferSize];
File ftmp = null;
for (int i = 0; i < fNames.length; i++) {
if (fNames[i] != null) {
FileInputStream fi = new FileInputStream(fNames[i]);
origin = new BufferedInputStream(fi, cntBufferSize);
ftmp = new File(fNames[i]);
ZipEntry entry = new ZipEntry(useFullFileNames ? fNames[i] : ftmp.getName());
out.putNextEntry(entry);
int count;
while ((count = origin.read(bBuffer, 0, cntBufferSize)) != -1) {
out.write(bBuffer, 0, count);
}
origin.close();
}
}
out.close();
return true;
} catch (Exception e) {
return false;
}
}
I'm zipping up the contents of a directory, but running into an error when trying to open the zipped up files.
Can anyone tell what's going on with my code? Perhaps I'm not allocating enough bytes?
Look inside zipDirectory() and you will see that I'm zipping up folders which contain special extension files.
Not sure where the error's occurring, so maybe someone can help me out there!
Much appreciated
private void zipDirectory() {
File lazyDirectory = new File(defaultSaveLocation);
File[] files = lazyDirectory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
System.out.println("Zipping up " + file);
zipContents(file);
}
}
}
public static void addToZip(String fileName, ZipOutputStream zos) throws FileNotFoundException, IOException {
System.out.println("Writing '" + fileName + "' to zip file");
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(fileName);
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
fis.close();
}
public static void zipContents(File dirToZip) {
List<File> fileList = new ArrayList<File>();
File[] filesToZip = dirToZip.listFiles();
for (File zipThis : filesToZip) {
String ext = "";
int i = zipThis.toString().lastIndexOf('.');
if (i > 0) {
ext = zipThis.toString().substring(i+1);
}
if(ext.matches("cpp|bem|gz|h|hpp|pl|pln|ppcout|vec|xml|csv")){
fileList.add(zipThis);
}
}
try {
FileOutputStream fos = new FileOutputStream(dirToZip.getName() + ".zip");
ZipOutputStream zos = new ZipOutputStream(fos);
for (File file : fileList) {
addToZip(file.toString(), zos);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Like most issues with IO streams in Java, your fault is almost certainly that you are not closing the streams properly. You need to add:
zos.finish(); // good practice
zos.close();
after the for loop.
For me the fix is that you need to do this for EVERY file entry
zos.finish()
zos.flush()
zos.closeEntry()
Then do the above things again to close the zos. Otherwise, the default windows can't open the zipped folder properly, but third-party application works.
This may also happen if you use a character-oriented writer (e.g. FileWriter) to create the unzipped files (that actually contain binary data)
I was unable to read files that I was extracting and switching to a binary output stream (FileOutputStream) fixed the issue