Creating zip archive in Java
我有一个7zip程序创建的文件。 我用deflate方法压缩它。 现在,我要在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // simplified code for zip creation in java import java.io.*; import java.util.zip.*; public class ZipCreateExample { public static void main(String[] args) throws Exception { // input file FileInputStream in = new FileInputStream("F:/sometxt.txt"); // out put file ZipOutputStream out = new ZipOutputStream(new FileOutputStream("F:/tmp.zip")); // name the file inside the zip file out.putNextEntry(new ZipEntry("zippedjava.txt")); // buffer size byte[] b = new byte[1024]; int count; while ((count = in.read(b)) > 0) { out.write(b, 0, count); } out.close(); in.close(); } } |
只是为了澄清一下,您为原始文件使用了7zip中的ZIP算法? 7zip也声称比其他供应商高2-10%的压缩率。我敢猜测,Java内置的ZIP算法的优化程度不及7zip中的那种。如果需要类似的压缩文件,最好的办法是从命令行调用7zip。
您是否要解压缩ZIP文件,更改其中的文件,然后重新压缩它以使其具有相同的MD5哈希值?散列旨在防止您这样做。
ZipOutputStream有几种调整压缩的方法:
公共无效setMethod(int方法)
Sets the default compression method
for subsequent entries. This default
will be used whenever the compression
method is not specified for an
individual ZIP file entry, and is
initially set to DEFLATED.
公共无效setLevel(int级别)
Sets the compression level for
subsequent entries which are DEFLATED.
The default setting is DEFAULT_COMPRESSION. level - the compression level (0-9)
当您添加类似以下内容时:
1 2 3 4 | ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(target)); zos.setMethod( ZipOutputStream.DEFLATED ); zos.setLevel( 5 ); ... |
它不会改善您的压缩率吗?
这是一个传递绝对路径的函数,它将创建一个与目录名称相同的zip文件(在该目录下,您希望对所有子文件夹和文件进行zip,所有内容都是!!),如果成功则返回true,否则返回false如果有的话。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | public class FileUtil { final static int BUFFER = 2048; private static Logger log = Logger.getLogger(FileUtil.class); public static boolean createZipArchive(String srcFolder) { try { BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream(new File(srcFolder+".zip")); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest)); byte data[] = new byte[BUFFER]; File subDir = new File(srcFolder); String subdirList[] = subDir.list(); for(String sd:subdirList) { // get a list of files from current directory File f = new File(srcFolder+"/"+sd); if(f.isDirectory()) { String files[] = f.list(); for (int i = 0; i < files.length; i++) { System.out.println("Adding:" + files[i]); FileInputStream fi = new FileInputStream(srcFolder +"/"+sd+"/" + files[i]); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(sd +"/"+files[i]); out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); out.flush(); } } } else //it is just a file { FileInputStream fi = new FileInputStream(f); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(sd); out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); out.flush(); } } } origin.close(); out.flush(); out.close(); } catch (Exception e) { log.info("createZipArchive threw exception:" + e.getMessage()); return false; } return true; } } |
要从同一源文件生成两个相同的zip文件(包括相同的md5sum),我建议使用相同的zip实用程序-始终使用相同的Java程序,或者始终使用7zip。
例如7zip实用程序有很多选项-其中许多只是可以自定义的默认值(或版本之间有所不同?),并且任何Java zip实现都必须明确设置这些选项。如果您的Java应用程序可以简单地调用外部" 7z"程序,则无论如何,您都可能会获得比自定义Java zip实现更好的性能。 (这也是map-reduce问题的一个很好的例子,您可以在其中轻松扩展实现。)
但是,如果您拥有服务器端生成的zip文件和客户端端生成的zip文件,则将遇到的主要问题是,该zip文件除了存储原始文件外还存储两件事:(1)文件名,以及(2)文件时间戳。如果其中任何一个已更改,那么生成的zip文件将具有不同的md5sum:
1 2 3 4 5 6 7 8 9 10 | $ ls tst1/ foo.tar $ cp -r tst1 tst2 $ ( cd tst1; zip foo.zip foo.tar ) ; ( cd tst2; zip foo.zip foo.tar ) ; md5sum tst?/foo.zip updating: foo.tar (deflated 20%) updating: foo.tar (deflated 20%) 359b82678a2e17c1ddbc795ceeae7b60 tst1/foo.zip b55c33c0414ff987597d3ef9ad8d1d08 tst2/foo.zip |
但是,使用" cp -p"(保留时间戳):
1 2 3 4 5 6 7 | $ cp -p -r tst1 tst2 $ ( cd tst1; zip foo.zip foo.tar ) ; ( cd tst2; zip foo.zip foo.tar ) ; md5sum tst?/foo.zip updating: foo.tar (deflated 20%) updating: foo.tar (deflated 20%) 359b82678a2e17c1ddbc795ceeae7b60 tst1/foo.zip 359b82678a2e17c1ddbc795ceeae7b60 tst2/foo.zip |
即使文件名和路径相同,您也会发现文件名和路径不同的问题。
请在下面的代码中找到具有zip和unzip功能的代码。希望它可以帮助某人。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | package com.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** * @author dinesh.lomte * */ public class ZipUtil { /** * * @param source * @param destination */ public static void unZip(String source, String destination) { String method ="unZip(String source, String destination)"; ZipInputStream zipInputStream = null; try { // Creating the ZipInputStream instance from the source file zipInputStream = new ZipInputStream(new FileInputStream(source)); // Getting the zipped file list entry ZipEntry zipEntry = zipInputStream.getNextEntry(); // Iterating through the file list entry while (zipEntry != null) { String fileName = zipEntry.getName(); File file = new File(new StringBuilder(destination) .append(File.separator) .append(AppUtil.getFileNameWithoutExtension( AppUtil.getNameFromPath(source))) .append(File.separator).append(fileName).toString()); // Creating non existing folders to avoid any FileNotFoundException // for compressed folder new File(file.getParent()).mkdirs(); FileOutputStream fileOutputStream = new FileOutputStream(file); byte[] buffer = new byte[1024]; int length; while ((length = zipInputStream.read(buffer)) > 0) { fileOutputStream.write(buffer, 0, length); } fileOutputStream.close(); zipEntry = zipInputStream.getNextEntry(); } } catch (IOException iOException) { System.out.println("Failed to unzip the ''{0}'' file located in ''{1}'' folder. Due to, {2}"); } finally { // Validating if zipInputStream instance in not null if (zipInputStream != null) { try { zipInputStream.closeEntry(); zipInputStream.close(); } catch (IOException iOException) { } } } } /** * Traverse a directory from the source folder location and get all files, * and add the file into files list. * * @param node */ public static void generateFileList( String source, File node, List<String> files) { // Validating if the node is a file if (node.isFile()) { files.add(generateZipEntry( source, node.getPath().toString())); } // Validating if the node is a directory if (node.isDirectory()) { String[] subNote = node.list(); for (String filename : subNote) { generateFileList(source, new File(node, filename), files); } } } /** * Format the file path to zip * @param source * @param file * @return */ private static String generateZipEntry(String source, String file) { return file.substring(source.length(), file.length()); } /** * * @param source * @param destination */ public static void zip(String source, String destination) { String method ="zip(String source, String destination)"; ZipOutputStream zipOutputStream = null; try { // Creating the zipOutputStream instance zipOutputStream = new ZipOutputStream( new FileOutputStream(destination)); List<String> files = new ArrayList<>(); generateFileList(source, new File(source), files); // Iterating the list of file(s) to zip/compress for (String file : files) { // Adding the file(s) to the zip ZipEntry zipEntry = new ZipEntry(file); zipOutputStream.putNextEntry(zipEntry); FileInputStream fileInputStream = new FileInputStream( new StringBuilder(source).append(File.separator) .append(file).toString()); int length; byte[] buffer = new byte[1024]; while ((length = fileInputStream.read(buffer)) > 0) { zipOutputStream.write(buffer, 0, length); } // Closing the fileInputStream instance fileInputStream.close(); // De-allocating the memory by assigning the null value fileInputStream = null; } } catch (IOException iOException) { System.out.println("Failed to zip the file(s) located in ''{0}'' folder. Due to, {1}"); } finally { // Validating if zipOutputStream instance in not null if (zipOutputStream != null) { try { zipOutputStream.closeEntry(); zipOutputStream.close(); } catch (IOException iOException) { } } } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package comm; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream;*emphasized text* import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class Zip1 { public static void main( String[] args ) { byte[] buffer = new byte[1024]; try{ File f= new File("E:\\\"); f.mkdirs(); File origFile= new File(f,"MyZipFile2.zip"); FileOutputStream fos = new FileOutputStream(origFile); ZipOutputStream zos = new ZipOutputStream(fos); ZipEntry ze= new ZipEntry("test.pdf"); zos.putNextEntry(ze); FileInputStream in = new FileInputStream("D:\\\\Test.pdf"); int len; while ((len = in.read(buffer)) > 0) { zos.write(buffer, 0, len); } in.close(); zos.closeEntry(); //remember close it zos.close(); System.out.println("Done"); }catch(IOException ex){ ex.printStackTrace(); } } } |