Fast zipping folder using java ParallelScatterZipCreator

2.8k views Asked by At

What should be the value of or initialize InputStreamSupplier? I was trying to zip all the files in a directory and that should be fast. So multi threading is the option i'm going for.

public class ScatterSample { 

    ParallelScatterZipCreator scatterZipCreator = new ParallelScatterZipCreator(); 
    ScatterZipOutputStream dirs = ScatterZipOutputStream.fileBased(File.createTempFile("scatter-dirs", "tmp")); 

    public ScatterSample() throws IOException { 
    } 

    public void addEntry(ZipArchiveEntry zipArchiveEntry, InputStreamSupplier streamSupplier) throws IOException { 
        if (zipArchiveEntry.isDirectory() && !zipArchiveEntry.isUnixSymlink()) 
            dirs.addArchiveEntry(ZipArchiveEntryRequest.createZipArchiveEntryRequest(zipArchiveEntry, streamSupplier)); 
        else 
            scatterZipCreator.addArchiveEntry( zipArchiveEntry, streamSupplier); 
    } 

    public void writeTo(ZipArchiveOutputStream zipArchiveOutputStream) 
            throws IOException, ExecutionException, InterruptedException { 
        dirs.writeTo(zipArchiveOutputStream); 
        dirs.close(); 
        scatterZipCreator.writeTo(zipArchiveOutputStream); 
    } 

}

FirstMain Class:

public class FirstMain {

    public FirstMain() {
        // TODO Auto-generated constructor stub
    }

    public static void compressFolder(String sourceFolder, String absoluteZipfilepath)
    {
        try
        {
            ScatterSample scatterSample=new ScatterSample();


            File srcFolder = new File(sourceFolder);
            if(srcFolder != null && srcFolder.isDirectory())
            {
                Iterator<File> i = FileUtils.iterateFiles(srcFolder, new String []{"pdf"}, true);


                File zipFile = new File(absoluteZipfilepath);

                OutputStream outputStream = new FileOutputStream(zipFile);

                ZipArchiveOutputStream zipArchiveOutputStream= new ZipArchiveOutputStream(outputStream);
                int srcFolderLength = srcFolder.getAbsolutePath().length() + 1;  // +1 to remove the last file separator

                while(i.hasNext())
                {
                    File file = i.next();                   
                    String relativePath  = file.getAbsolutePath().substring(srcFolderLength);



                    InputStreamSupplier streamSupplier=new InputStreamSupplier(){

                        @Override
                        public InputStream get() {
                            // TODO Auto-generated method stub
                            return null;
                        }
                    }; 

                    ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(relativePath);
                    scatterSample.addEntry(zipArchiveEntry, streamSupplier);


                }


                scatterSample.writeTo(zipArchiveOutputStream);

            }
        }catch (Exception e) {
            e.printStackTrace();
        }         
    }
     public static void main( String[] args )
     {
         compressFolder("C:\\Users\\akatm\\Desktop\\Stuff\\zipdata\\Newtry\\","C:/Users/akatm/Desktop/Stuff/Newtry.zip");
     }

}
2

There are 2 answers

0
dlauzon On

The get() method must return an InputStream to the file.
You could define an internal class as the following:

static class FileInputStreamSupplier implements InputStreamSupplier {
    private Path sourceFile;

    FileInputStreamSupplier(Path sourceFile) {
        this.sourceFile = sourceFile;
    }

    @Override
    public InputStream get() {
        InputStream is = null;
        try {
            is = Files.newInputStream(sourceFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return is;
    }
}

That you could then invoke as:

scatterSample.addEntry(zipArchiveEntry, new FileInputStreamSupplier(file.toPath());
0
Roberto Dominguez Cazarin On

You need to set the compress method in the ZipEntry

ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(relativePath);
zipArchiveEntry.setMethod(ZipArchiveEntry.STORED);
scatterSample.addEntry(zipArchiveEntry, streamSupplier);

if you don't set the compress method, the method throws an exception.