2

I am trying to add some files to a ZIP file, it creates the file but does not add anything into it. Code 1:

String fulldate = year + "-" + month + "-" + day + "-" + min;

File dateFolder = new File("F:\\" + compname + "\\" + fulldate);
dateFolder.mkdir();

String zipName = "F:\\" + compname + "\\" + fulldate + "\\" + fulldate + ".zip";

zipFolder(tobackup, zipName);

My function:

public static void zipFolder(File folder, String name) throws Exception {
    byte[] buffer = new byte[18024];

    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(name));
    FileInputStream in = new FileInputStream(folder);

    out.putNextEntry(new ZipEntry(name));

    int len;

    while((len = in.read(buffer)) > 0) {
        out.write(buffer, 0, len);
    }

    out.closeEntry();
    in.close();
    out.close();
}

Edit: I found the problem, it was just having trouble writing files from the C:\ drive into a ZIP in the F:\ drive

cheese5505
  • 962
  • 5
  • 14
  • 30
  • If you want to iterate over the files in the given folder, use the [`listFiles()`-method](http://docs.oracle.com/javase/6/docs/api/java/io/File.html#listFiles()) of your `File`-object. – Lukas Knuth Apr 11 '12 at 10:18

3 Answers3

15

You can't zip folders, only files. To zip folders, you have to add all the subfiles manually. I wrote this class that does the job. You can have it for free :)

The usage would be this:

List<File> sources = new ArrayList<File>();
sources.add(tobackup);
Packager.packZip(new File(zipName), sources);

Here is the class:

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

public class Packager
{
    public static void packZip(File output, List<File> sources) throws IOException
    {
        System.out.println("Packaging to " + output.getName());
        ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(output));
        zipOut.setLevel(Deflater.DEFAULT_COMPRESSION);

        for (File source : sources)
        {
            if (source.isDirectory())
            {
                zipDir(zipOut, "", source);
            } else
            {
                zipFile(zipOut, "", source);
            }
        }
        zipOut.flush();
        zipOut.close();
        System.out.println("Done");
    }

    private static String buildPath(String path, String file)
    {
        if (path == null || path.isEmpty())
        {
            return file;
        } else
        {
            return path + "/" + file;
        }
    }

    private static void zipDir(ZipOutputStream zos, String path, File dir) throws IOException
    {
        if (!dir.canRead())
        {
            System.out.println("Cannot read " + dir.getCanonicalPath() + " (maybe because of permissions)");
            return;
        }

        File[] files = dir.listFiles();
        path = buildPath(path, dir.getName());
        System.out.println("Adding Directory " + path);

        for (File source : files)
        {
            if (source.isDirectory())
            {
                zipDir(zos, path, source);
            } else
            {
                zipFile(zos, path, source);
            }
        }

        System.out.println("Leaving Directory " + path);
    }

    private static void zipFile(ZipOutputStream zos, String path, File file) throws IOException
    {
        if (!file.canRead())
        {
            System.out.println("Cannot read " + file.getCanonicalPath() + " (maybe because of permissions)");
            return;
        }

        System.out.println("Compressing " + file.getName());
        zos.putNextEntry(new ZipEntry(buildPath(path, file.getName())));

        FileInputStream fis = new FileInputStream(file);

        byte[] buffer = new byte[4092];
        int byteCount = 0;
        while ((byteCount = fis.read(buffer)) != -1)
        {
            zos.write(buffer, 0, byteCount);
            System.out.print('.');
            System.out.flush();
        }
        System.out.println();

        fis.close();
        zos.closeEntry();
    }
}

Enjoy!

EDIT: To check if the program is still busy, you can add the three lines I marked with a (*)

EDIT 2: Try the new code. On my platform, it runs correct (OS X). I'm not sure but, there might be some limited read permissions for files in Windows in AppData.

Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • Thanks! I'll see how it goes! EDIT: It looked good, it DID compress it (:D), but it's apparently invalid. Error: The Compressed (zipped) Folder 'F:\David-PC\2012-03-11-25\2012-03-11-25.zip' is invalid. – cheese5505 Apr 11 '12 at 10:23
  • Wait - Hmm, weird. It automatically terminated itself for no reason. "Done." diddn't appear. – cheese5505 Apr 11 '12 at 10:29
  • @cheese5505: Make sure that you give the program the needed time. Compression takes some time. Make sure the application is terminated before you try to open the zip. You could add a `System.out.print(".");` in the compression loop, to see if the program is still busy or not. – Martijn Courteaux Apr 11 '12 at 10:31
  • Well, I did. I exported it and ran it through CMD, but it stops suddenly. Is there a time limit? Here's the last data it sends: Leaving Directory David/AppData/Local/Apple Computer/QuickTime Adding Directory David/AppData/Local/Apple Computer/WebKit Leaving Directory David/AppData/Local/Apple Computer/WebKit Leaving Directory David/AppData/Local/Apple Computer Adding Directory David/AppData/Local/Application Data C:\Users\David\Desktop> – cheese5505 Apr 11 '12 at 10:35
  • Still stopped, but it went alot further. – cheese5505 Apr 11 '12 at 21:33
  • 1
    You'd think if java was going to provide a zip api, there would be a method like the one you just wrote. Nice work. – Steve Apr 19 '17 at 15:36
  • So you mean that to add an entry to an existing zip, you need to create a new file with the original zipped content, then add the new entry to it? Sounds inefficient but then I guess it's unavoidable since zip format is at the end of the file... – Matthieu Jun 28 '21 at 11:07
2

See also ZeroTurnaround's Zip library. It has such features as (citation):

  • pack and unpack directories recursively
  • iterate through ZIP entries
Grzegorz Grzybek
  • 6,152
  • 3
  • 29
  • 42
1

I'll add another way using Java 7 NIO FileSystem. It uses the fact that JAR files are actually ZIP:

static public void addToZip(Path zip, Path file) throws IOException {
    Map<String,String> env = new HashMap<>();
    env.put("create", "false"); // We don't create the file but modify it
    
    URI uri = URI.create("jar:file:"+zip.toString());
    try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
        Path f = zipfs.getPath(file.getFileName().toString());
        Files.copy(file, f, StandardCopyOption.REPLACE_EXISTING);
    }
}
Matthieu
  • 2,736
  • 4
  • 57
  • 87