Naik Ashwini
Naik Ashwini

Reputation: 808

Creation of a zip with multiple files having same name

I want to zip multiple files from different locations into one.

I referred https://examples.javacodegeeks.com/core-java/util/zip/create-zip-file-from-multiple-files-with-zipoutputstream/

Here is my code

public class CreateZipFileFromMultipleFilesWithZipOutputStream {

public static void main(String[] args) {

    String zipFile = "C:/archive.zip";

    String[] srcFiles = { "C:/data1/srcfile1.txt", "C:/data2/srcfile2.txt", "C:/data3/srcfile2.txt"};

    try {

        FileOutputStream fos = new FileOutputStream(zipFile);

        ZipOutputStream zos = new ZipOutputStream(fos);

        for (int i=0; i < srcFiles.length; i++) {

            File srcFile = new File(srcFiles[i]);

            ZipEntry zipEntry = new ZipEntry(srcFile.getName());
            zos.putNextEntry(zipEntry);
            zos.write(Files.readAllBytes(srcFile.toPath()));
            zos.closeEntry();
        }

        // close the ZipOutputStream
        zos.close();

    }
    catch (IOException ioe) {
        System.out.println("Error creating zip file: " + ioe);
    }
}

}

This throws an exception: Error creating zip file: java.util.zip.ZipException: duplicate entry: dsdc.zip

Is there any way to check if the file exists in zip stream? So in that case I can append _1 to the duplicate file name?

Upvotes: 0

Views: 4429

Answers (2)

Naik Ashwini
Naik Ashwini

Reputation: 808

One solution is:

            Set<String> uniqueFilenames = new HashSet<>();
            for (int i=0; i < srcFiles.length; i++) {

                File srcFile = new File(srcFiles[i]);

                String name = FilenameUtils.getBaseName(srcFile.getName());
                String originalName = name;


                for (int j = 1; !uniqueFilenames.add(name); j++) {
                    name = originalName + "_" + j;
                }

                ZipEntry zipEntry = new ZipEntry(name + "." + FilenameUtils.getExtension(srcFile.getName()));
                zos.putNextEntry(zipEntry);
                zos.write(Files.readAllBytes(srcFile.toPath()));
                zos.closeEntry();

@Thorbjørn Ravn also suggested something like this. But is there any other way?

Upvotes: 1

In OpenJDK 8 this is handled by the private field "names" in ZipOutputStream which is not publicly exposed. You are very clearly expected to handle this yourself.

Just have a HashSet containing filenames which you successfully added to the zip file, and check if the name is previously seen before trying to add a new file. If so, modify accordingly.

That said, you should reconsider your solution design if it may add several copies of the same file to a zip file. Either include directories to make the files unique, or just skip anything previously seen.

Upvotes: 1

Related Questions