使用Java自带的类 java.util.zip进行文件/目录的压缩的话,有一点不足,不支持中文的名件/目录命名,如果有中文名,那么打包就会失败。本人经过一段时间的摸索和实践,发现在一般的Ant.jar类库中也有zip类,import org.apache.tools.zip.*,能够解决不支持中文文件目录的问题,同时,Ant的获得途径也比较多,一般的应用服务器中有这个包,实在不行去下载个tomcat5.X,里面也有ant.jar,本人经过测试,可以使用。
- import java.io.File;
- import org.apache.tools.zip.ZipOutputStream;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- /**
- *
- * @author XL
- *
- */
- public class Zip04 {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // 需打包的文件夾
- String inputFileName = "c:\\tt2";
- try {
- zip(inputFileName);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void zip(String inputFileName) throws Exception {
- String zipFileName = "c:\\test.zip";// 打包后文件名字
- System.out.println(zipFileName);
- zip(zipFileName, new File(inputFileName));
- }
- public static void zip(String zipFileName, File inputFile) throws Exception {
- ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
- zipFileName));
- zip(out, inputFile, "");
- System.out.println("zip done");
- out.close();
- }
- public static void zip(ZipOutputStream out, File f, String base)
- throws Exception {
- if (f.isDirectory()) {
- File[] fl = f.listFiles();
- out.putNextEntry(new org.apache.tools.zip.ZipEntry(base + "/"));
- base = base.length() == 0 ? "" : base + "/";
- for (int i = 0; i < fl.length; i++) {
- zip(out, fl[i], base + fl[i].getName());
- }
- } else {
- out.putNextEntry(new org.apache.tools.zip.ZipEntry(base));
- FileInputStream in = new FileInputStream(f);
- int b;
- System.out.println(base);
- while ((b = in.read()) != -1) {
- out.write(b);
- }
- in.close();
- }
- }
- }
类ZipInputStream读出ZIP文件序列(简单地说就是读出这个ZIP文件压缩了多少文件),而类ZipFile使用内嵌的随机文件访问机制读出其中的文件内容,所以不必顺序的读出ZIP压缩文件序列。
ZipInputStream和ZipFile之间另外一个基本的不同点在于高速缓冲的使用方面。当文件使用ZipInputStream和FileInputStream流读出的时候,ZIP条目不使用高速缓冲。然而,如果使用ZipFile(文件名)来打开文件,它将使用内嵌的高速缓冲,所以如果ZipFile(文件名)被重复调用的话,文件只被打开一次。缓冲值在第二次打开时使用。如果你工作在UNIX系统下,这是什么作用都没有的,因为使用ZipFile打开的所有ZIP文件都在内存中存在映射,所以使用ZipFile的性能优于ZipInputStream。然而,如果同一ZIP文件的内容在程序执行期间经常改变,或是重载的话,使用ZipInputStream就成为你的首选了。
下面显示了使用类ZipFile来解压一个ZIP文件的过程:
-
通过指定一个被读取的ZIP文件,或者是文件名,或者是一个文件对象来创建一个ZipFile对象:
- ZipFile zipfile = new ZipFile("figs.zip");
ZipFile zipfile = new ZipFile("figs.zip");
-
使用entries方法,返回一个枚举对象,循环获得文件的ZIP条目对象:
- while(e.hasMoreElements()) {
- entry = (ZipEntry) e.nextElement();
- // read contents and save them
- }
while(e.hasMoreElements()) { entry = (ZipEntry) e.nextElement(); // read contents and save them }
-
ZIP条目作为参数传递给getInputStream方法,可以读取ZIP文件中指定条目的内容,能过其返回的输入流(InputStram)对象可以方便的读出ZIP条目的内容:
- is = new BufferedInputStream(zipfile.getInputStream(entry));
is = new BufferedInputStream(zipfile.getInputStream(entry));
-
获取ZIP条目的文件名,创建输出流,并保存:
- byte data[] = new byte[BUFFER];
- FileOutputStream fos = new FileOutputStream(entry.getName());
- dest = new BufferedOutputStream(fos, BUFFER);
- while ((count = is.read(data, 0, BUFFER)) != -1) {
- dest.write(data, 0, count);
- }
byte data[] = new byte[BUFFER]; FileOutputStream fos = new FileOutputStream(entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = is.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); }
-
最后关闭所有的输入输出流
- dest.flush();
- dest.close();
- is.close();
dest.flush(); dest.close(); is.close();
完整代码:
- public class UnZip2 {
- static final int BUFFER = 2048;
- public static void main(String argv[]) {
- String fileName = "c:/testlog.zip";
- String unZipDir = "c:/2/2/";
- unZip(fileName, unZipDir);
- }
- public static void unZip(String fileName, String unZipDir) {
- try {
- // 先判断目标文件夹是否存在,如果不存在则新建,如果父目录不存在也新建
- File f = new File(unZipDir);
- if (!f.exists()) {
- f.mkdirs();
- }
- BufferedOutputStream dest = null;
- BufferedInputStream is = null;
- ZipEntry entry;
- ZipFile zipfile = new ZipFile(fileName);
- Enumeration e = zipfile.entries();
- while (e.hasMoreElements()) {
- entry = (ZipEntry) e.nextElement();
- System.out.println("Extracting: " + entry);
- is = new BufferedInputStream(zipfile.getInputStream(entry));
- int count;
- byte data[] = new byte[BUFFER];
- FileOutputStream fos = new FileOutputStream(unZipDir + "/"
- + entry.getName());
- System.out.println("entry.getName(): " + entry.getName());
- dest = new BufferedOutputStream(fos, BUFFER);
- while ((count = is.read(data, 0, BUFFER)) != -1) {
- dest.write(data, 0, count);
- }
- dest.flush();
- dest.close();
- is.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static boolean makeDir(String unZipDir) {
- boolean b = false;
- try {
- File f = new File(unZipDir);
- if (!f.exists()) {
- b = f.mkdirs();
- }
- } catch (Exception e) {
- e.printStackTrace();
- return b;
- }
- return b;
- }
- }
首先我们实现最简单的解压缩zip文件,该zip文件中不包含文件夹,也不含中文名。
- /**
- * <pre>
- * 参考:
- * http://www.ibm.com/developerworks/cn/java/l-compress/index.html
- * </pre>
- */
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.util.zip.ZipEntry;
- import java.util.zip.ZipInputStream;
- public class UnZip {
- /** 定义一个2K的缓冲区 */
- static final int BUFFER = 2048;
- public static void main(String[] args) {
- String fileName = "c:/testlog.zip";
- // String unZipDir = "c:/abcd/abcd/abcd/abcd/abcd/";
- String unZipDir = "c:/1/2/";
- unZip(fileName, unZipDir);
- // System.out.println(makeDir(unZipDir));
- }
- /**
- * @param fileName
- * String 待解压缩的文件名
- * @param unZipDir
- * String 存放解压缩后生成的文件的文件夹
- */
- public static void unZip(String fileName, String unZipDir) {
- try {
- // 先判断目标文件夹是否存在,如果不存在则新建,如果父目录不存在也新建
- File f = new File(unZipDir);
- if (!f.exists()) {
- f.mkdirs();
- }
- BufferedOutputStream dest = null;
- // 将用文件输入流读入ZIP文件
- FileInputStream fis = new FileInputStream(fileName);
- // 类ZipInputStream读取ZIP文件
- ZipInputStream zis = new ZipInputStream(
- new BufferedInputStream(fis));
- ZipEntry entry;
- String newFileName = "";
- // ZIP输入流打开后,你可以使用getNextEntry方法来读取ZIP文件中的条目数,
- // 该方法返回一个ZipEntry对象。如果到达文件的尾部,getNextEntry返回null
- while ((entry = zis.getNextEntry()) != null) {
- System.out.println("Extracting: " + entry);
- int count;
- byte data[] = new byte[BUFFER];
- // write the files to the disk
- newFileName = unZipDir + "/" + entry.getName();
- System.out.println("newFileName: " + newFileName);
- FileOutputStream fos = new FileOutputStream(newFileName);
- dest = new BufferedOutputStream(fos, BUFFER);
- while ((count = zis.read(data, 0, BUFFER)) != -1) {
- dest.write(data, 0, count);
- }
- dest.flush();
- dest.close();
- }
- zis.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static boolean makeDir(String unZipDir) {
- boolean b = false;
- try {
- File f = new File(unZipDir);
- if (!f.exists()) {
- b = f.mkdirs();
- }
- } catch (Exception e) {
- e.printStackTrace();
- return b;
- }
- return b;
- }
- }