当前位置: 移动技术网 > IT编程>开发语言>Java > java ant包中的org.apache.tools.zip实现压缩和解压缩实例详解

java ant包中的org.apache.tools.zip实现压缩和解压缩实例详解

2019年07月22日  | 移动技术网IT编程  | 我要评论

java ant包中的org.apache.tools.zip实现压缩和解压缩实例详解

其实apache中的ant包(请自行google之ant.jar)中有一个更好的类,已经支持中文了,我们就不重复制造轮子了,拿来用吧,
这里最主要的功能是实现了 可以指定多个文件 到同一个压缩包的功能

用org.apache.tools.zip压缩/解压缩zip文件的例子,用来解决中文乱码问题。

实例代码:

import java.io.bufferedinputstream;
import java.io.bufferedoutputstream;
import java.io.file;
import java.io.fileinputstream;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.util.arraylist;
import java.util.list;
import java.util.zip.crc32;
import java.util.zip.checkedoutputstream;
import java.util.zip.deflater;

import org.apache.tools.zip.zipentry;
import org.apache.tools.zip.zipoutputstream;

/**
 * 功能:使用apache ant里提供的org.apache.tools.zip实现zip压缩和解压 (支持中文文件名)
 * 解决了由于java.util.zip包不支持汉字的问题。 使用java.util.zip包时,当zip文件中有名字为中文的文件时,
 * 就会出现异常:"exception in thread "main " java.lang.illegalargumentexception at
 * java.util.zip.zipinputstream.getutf8string(zipinputstream.java:285)
 * 
 * @author 夏明龙 e-mail:邮箱
 * @version 创建时间:2013-3-22 上午10:40:21 类说明:
 */
public class antziputil {
 private static list list = new arraylist();

 private static list listfile(string path) {
 file file = new file(path);
 string[] array = null;
 string stemp = "";

 if (!file.isdirectory()) {
  return null;
 }
 array = file.list();
 if (array.length > 0) {
  for (int i = 0; i < array.length; i++) {
  stemp = path + array[i];
  file = new file(stemp);
  if (file.isdirectory()) {
   listfile(stemp + "/");
  } else
   list.add(stemp);
  }
 } else {
  return null;
 }

 return list;
 }

 public static void zip(string needtozipfilepath, string zipfilepath){
 try {
  byte[] b = new byte[512];

  file needtozipfile = new file(needtozipfilepath);

  if (!needtozipfile.exists()) {
  system.err.println("指定的要压缩的文件或目录不存在.");
  return;
  }

  string zipfile = zipfilepath;
  file targetfile = new file(zipfile.substring(0, zipfile.indexof("\\") + 1));

  if (!targetfile.exists()) {
  system.out.println("指定的目标文件或目录不存在.");
  return;
  }

  string filepath = needtozipfilepath;
  list filelist = listfile(filepath);
  fileoutputstream fileoutputstream = new fileoutputstream(zipfile);
  checkedoutputstream cs = new checkedoutputstream(fileoutputstream,new crc32());
  zipoutputstream out = new zipoutputstream(new bufferedoutputstream(cs));

  for (int i = 0; i < filelist.size(); i++) {
  inputstream in = new fileinputstream((string) filelist.get(i));
  string filename = ((string) filelist.get(i)).replace(file.separatorchar, '/');
  filename = filename.substring(filename.indexof("/") + 1);
  zipentry e = new zipentry(filename);
  out.putnextentry(e);
  int len = 0;
  while ((len = in.read(b)) != -1) {
   out.write(b, 0, len);
  }
  out.closeentry();
  }
  out.close();
 } catch (exception e) {
  e.printstacktrace();
 }
 }

 // ///////////////////////////////////////
 /**
 * 压缩文件 或者 文件夹
 * 
 * @param basedirname
 *      压缩的根目录
 * @param filename
 *      根目录下待压缩的文件或文件夹名
 * @param targetfilename
 *      目标zip 文件 星号 "*" 表示压缩根目录下的全部文件
 * 
 */
 public static boolean zip(string basedirname, string[] filenames,
  string targetfilename, string encoding) {
 boolean flag = false;
 try {
  // 判断 "压缩的根目录"是否存在! 是否是一个文件夹!
  file basedir = new file(basedirname);
  if (!basedir.exists() || (!basedir.isdirectory())) {
  system.err.println("压缩失败! 根目录不存在: " + basedirname);
  return false;
  }

  // 得到这个 "压缩的根目录" 的绝对路径
  string basedirpath = basedir.getabsolutepath();

  // 由这个 "目标 zip 文件" 文件名得到一个 压缩对象 zipoutputstream
  file targetfile = new file(targetfilename);
  zipoutputstream out = new zipoutputstream(new fileoutputstream(
   targetfile));
  // 中文有乱码,引进下面的改造类
  // cnzipoutputstream out = new cnzipoutputstream(new
  // fileoutputstream(targetfile),encoding);

  // 设置压缩编码apache ant有个包专门处理zip文件,可以指定文件名的编码方式。由此可以解决问题。例如:用
  // org.apache.tools.zip.zipoutputstream代替java.util.zip.zipoutputstream。zipoutputstream
  // out = .....; out.setencoding("gbk");
  // out.setencoding("gbk");//设置为gbk后在windows下就不会乱码了,如果要放到linux或者unix下就不要设置了
  out.setencoding(encoding);

  // "*" 表示压缩包括根目录 basedirname 在内的全部文件 到 targetfilename文件下
  if (filenames.equals("*")) {
  antziputil.dirtozip(basedirpath, basedir, out);
  } else {
  file[] files = new file[filenames.length];
  for (int i = 0; i < files.length; i++) {
   // 根据 parent 抽象路径名和 child 路径名字符串创建一个新 file 实例。
   files[i] = new file(basedir, filenames[i]);
  }
  if (files[0].isfile()) {
   // 调用本类的一个静态方法 压缩一个文件
   // compressutil.filetozip(basedirpath, file, out);
   antziputil.filestozip(basedirpath, files, out);
  }

  }
  out.close();
  // system.out.println("压缩成功! 目标文件名为: " + targetfilename);
  flag = true;
 } catch (filenotfoundexception e) {
  e.printstacktrace();
 } catch (ioexception e) {
  e.printstacktrace();
 }
 return flag;
 }

 /**
 * 将文件压缩到zip 输出流
 * 
 * @param basedirpath
 *      根目录路径
 * @param file
 *      要压缩的文件
 * @param out
 *      输出流
 * @throws ioexception
 */
 private static void filetozip(string basedirpath, file file,
  zipoutputstream out) throws ioexception {
 //
 fileinputstream in = null;
 org.apache.tools.zip.zipentry entry = null;
 // 创建复制缓冲区 1024*4 = 4k
 byte[] buffer = new byte[1024 * 4];
 int bytes_read = 0;
 if (file.isfile()) {
  in = new fileinputstream(file);
  // 根据 parent 路径名字符串和 child 路径名字符串创建一个新 file 实例
  string zipfilename = getentryname(basedirpath, file);
  entry = new org.apache.tools.zip.zipentry(zipfilename);
  // "压缩文件" 对象加入 "要压缩的文件" 对象
  out.putnextentry(entry);
  // 现在是把 "要压缩的文件" 对象中的内容写入到 "压缩文件" 对象
  while ((bytes_read = in.read(buffer)) != -1) {
  out.write(buffer, 0, bytes_read);
  }
  out.closeentry();
  in.close();
  // system.out.println("添加文件" + file.getabsolutepath()+ "被添加到 zip
  // 文件中!");
 }
 }

 /**
 * 多个文件目录压缩到zip 输出流
 * 
 * @param basedirpath
 * @param files
 * @param out
 * @throws ioexception
 */
 @suppresswarnings("unused")
 private static void filestozip(string basedirpath, file[] files,
  zipoutputstream out) throws ioexception {
 // 遍历所有的文件 一个一个地压缩
 for (int i = 0; i < files.length; i++) {
  file file = files[i];
  if (file.isfile()) {
  // 调用本类的一个静态方法 压缩一个文件
  antziputil.filetozip(basedirpath, file, out);
  } else {
  /*
   * 这是一个文件夹 所以要再次得到它下面的所有的文件 这里是自己调用自己..............递归..........
   */
  antziputil.dirtozip(basedirpath, file, out);
  }
 }
 }

 /**
 * 将文件目录压缩到zip 输出流
 * 
 * @param basedirpath
 * @param dir
 * @param out
 * @throws ioexception
 */
 private static void dirtozip(string basedirpath, file dir,
  zipoutputstream out) throws ioexception {
 // 得到一个文件列表 (本目录下的所有文件对象集合)
 file[] files = dir.listfiles();
 // 要是这个文件集合数组的长度为 0 , 也就证明了这是一个空的文件夹,虽然没有再循环遍历它的必要,但是也要把这个空文件夹也压缩到目标文件中去
 if (files.length == 0) {
  // 根据 parent 路径名字符串和 child 路径名字符串创建一个新 file 实例
  string zipfilename = getentryname(basedirpath, dir);
  org.apache.tools.zip.zipentry entry = new org.apache.tools.zip.zipentry(
   zipfilename);
  out.putnextentry(entry);
  out.closeentry();
 } else {
  // 遍历所有的文件 一个一个地压缩
  for (int i = 0; i < files.length; i++) {
  file file = files[i];
  if (file.isfile()) {
   // 调用本类的一个静态方法 压缩一个文件
   antziputil.filetozip(basedirpath, file, out);
  } else {
   /*
   * 这是一个文件夹 所以要再次得到它下面的所有的文件
   * 这里是自己调用自己..............递归..........
   */
   antziputil.dirtozip(basedirpath, file, out);
  }
  }
 }
 }

 /**
 * 获取 待压缩文件在 zip 文件中的 entry的名字,即相对于根目录的相对路径名
 * 
 * @param basedirpath
 *      根目录
 * @param file
 * @return
 */
 private static string getentryname(string basedirpath, file file) {
 /**
  * 改变 basedirpath 的形式 把 "c:/temp" 变成 "c:/temp/"
  */
 if (!basedirpath.endswith(file.separator)) {
  basedirpath += file.separator;
 }
 string filepath = file.getabsolutepath();
 /**
  * 测试此抽象路径名表示的文件是否是一个目录。 要是这个文件对象是一个目录 则也要变成 后面带 "/" 这个文件对象类似于
  * "c:/temp/人体写真/1.jpg" 要是这个文件是一个文件夹 则也要变成 后面带 "/"
  * 因为你要是不这样做,它也会被压缩到目标文件中 但是却不能正解显示 也就是说操作系统不能正确识别它的文件类型(是文件还是文件夹)
  */
 if (file.isdirectory()) {
  filepath += "/";
 }
 int index = filepath.indexof(basedirpath);
 return filepath.substring(index + basedirpath.length());
 }

 // //////////////////////////解压缩////////////////////////////////////////
 /**
 * 调用org.apache.tools.zip实现解压缩,支持目录嵌套和中文名
 * 也可以使用java.util.zip不过如果是中文的话,解压缩的时候文件名字会是乱码。原因是解压缩软件的编码格式跟java.util.zip.zipinputstream的编码字符集(固定是utf-8)不同
 * 
 * @param zipfilename
 *      要解压缩的文件
 * @param outputdirectory
 *      要解压到的目录
 * @throws exception
 */
 public static boolean unzip(string zipfilename, string outputdirectory) {
 boolean flag = false;
 try {
  org.apache.tools.zip.zipfile zipfile = new org.apache.tools.zip.zipfile(
   zipfilename);
  java.util.enumeration e = zipfile.getentries();
  org.apache.tools.zip.zipentry zipentry = null;
  createdirectory(outputdirectory, "");
  while (e.hasmoreelements()) {
  zipentry = (org.apache.tools.zip.zipentry) e.nextelement();
  // system.out.println("unziping " + zipentry.getname());
  if (zipentry.isdirectory()) {
   string name = zipentry.getname();
   name = name.substring(0, name.length() - 1);
   file f = new file(outputdirectory + file.separator + name);
   f.mkdir();
   system.out.println("创建目录:" + outputdirectory
    + file.separator + name);
  } else {
   string filename = zipentry.getname();
   filename = filename.replace('\\', '/');
   // system.out.println("测试文件1:" +filename);
   if (filename.indexof("/") != -1) {
   createdirectory(outputdirectory, filename.substring(0,
    filename.lastindexof("/")));
   filename = filename.substring(
    filename.lastindexof("/") + 1, filename
     .length());
   }

   file f = new file(outputdirectory + file.separator
    + zipentry.getname());

   f.createnewfile();
   inputstream in = zipfile.getinputstream(zipentry);
   fileoutputstream out = new fileoutputstream(f);

   byte[] by = new byte[1024];
   int c;
   while ((c = in.read(by)) != -1) {
   out.write(by, 0, c);
   }
   out.close();
   in.close();
  }
  flag = true;
  }
 } catch (exception ex) {
  ex.printstacktrace();
 }
 return flag;
 }

 /**
 * 创建目录
 * 
 * @param directory
 *      父目录
 * @param subdirectory
 *      子目录
 */
 private static void createdirectory(string directory, string subdirectory) {
 string dir[];
 file fl = new file(directory);
 try {
  if (subdirectory == "" && fl.exists() != true)
  fl.mkdir();
  else if (subdirectory != "") {
  dir = subdirectory.replace('\\', '/').split("/");
  for (int i = 0; i < dir.length; i++) {
   file subfile = new file(directory + file.separator + dir[i]);
   if (subfile.exists() == false)
   subfile.mkdir();
   directory += file.separator + dir[i];
  }
  }
 } catch (exception ex) {
  system.out.println(ex.getmessage());
 }
 }

 // /////////////////////////////////////

 public static void main(string[] temp) {
 // 压缩
 string basedirname = "c:\\";
 string[] filenames = { "中文1.doc", "中文2.doc" };
 string zipfilename = "c:\\中文.zip";
 // 压缩多个指定的文件 到zip
  system.out.println(antziputil.zip(basedirname, filenames,zipfilename,"gbk"));

 //压缩一个文件夹 到zip
 string sourcepath = "c:\\test\\";
 string zipfilepath = "c:\\中文2.zip";
 antziputil.zip(sourcepath, zipfilepath);

 //解压缩
 //system.out.println(antziputil.unzip("c:\\中文.zip", "c:\\中文"));
 }

}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网