public static void copyZipWithoutEmptyDirectories ( final File inputFile , final File outputFile ) throws IOException { final byte [ ] buf = new byte [ 0x2000 ] ; final ZipFile inputZip = new ZipFile ( inputFile ) ; final ZipOutputStream outputStream = new ZipOutputStream ( new FileOutputStream ( outputFile ) ) ; try { // read a the entries of the input zip file and sort them final Enumeration < ? extends ZipEntry > e = inputZip . entries ( ) ; final ArrayList < ZipEntry > sortedList = new ArrayList < ZipEntry > ( ) ; while ( e . hasMoreElements ( ) ) { final ZipEntry entry = e . nextElement ( ) ; sortedList . add ( entry ) ; } Collections . sort ( sortedList , new Comparator < ZipEntry > ( ) { public int compare ( ZipEntry o1 , ZipEntry o2 ) { String n1 = o1 . getName ( ) , n2 = o2 . getName ( ) ; if ( metaOverride ( n1 , n2 ) ) { return - 1 ; } if ( metaOverride ( n2 , n1 ) ) { return 1 ; } return n1 . compareTo ( n2 ) ; } // make sure that META-INF/MANIFEST.MF is always the first entry after META-INF/ private boolean metaOverride ( String n1 , String n2 ) { return ( n1 . startsWith ( "META-INF/" ) && ! n2 . startsWith ( "META-INF/" ) ) || ( n1 . equals ( "META-INF/MANIFEST.MF" ) && ! n2 . equals ( n1 ) && ! n2 . equals ( "META-INF/" ) ) || ( n1 . equals ( "META-INF/" ) && ! n2 . equals ( n1 ) ) ; } } ) ; // treat them again and write them in output, wenn they not are empty directories for ( int i = sortedList . size ( ) - 1 ; i >= 0 ; i -- ) { final ZipEntry inputEntry = sortedList . get ( i ) ; final String name = inputEntry . getName ( ) ; final boolean isEmptyDirectory ; if ( inputEntry . isDirectory ( ) ) { if ( i == sortedList . size ( ) - 1 ) { // no item afterwards; it was an empty directory isEmptyDirectory = true ; } else { final String nextName = sortedList . get ( i + 1 ) . getName ( ) ; isEmptyDirectory = ! nextName . startsWith ( name ) ; } } else { isEmptyDirectory = false ; } if ( isEmptyDirectory ) { sortedList . remove ( i ) ; } } // finally write entries in normal order for ( int i = 0 ; i < sortedList . size ( ) ; i ++ ) { final ZipEntry inputEntry = sortedList . get ( i ) ; final ZipEntry outputEntry = new ZipEntry ( inputEntry ) ; outputStream . putNextEntry ( outputEntry ) ; ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ; final InputStream is = inputZip . getInputStream ( inputEntry ) ; IoUtil . pipe ( is , baos , buf ) ; is . close ( ) ; outputStream . write ( baos . toByteArray ( ) ) ; } } finally { outputStream . close ( ) ; inputZip . close ( ) ; } }
Create a copy of an zip file without its empty directories .