java 打包多文件,单个文件,解压缩源码

package dtm.tools;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 *
 * ************************************************* 使用 ZipOutputStream
 * 可以实现文件压缩, 所有写入到 ZipOutputStream 输出流的数据都会被 ZIP 格式压缩!
 *
 * 每个压缩的文件或者目录在 ZIP 文件中都对应一个 ZipEntry 对象, 每个 ZipEntry 都有一个name属性,表示它相对于 Zip
 * 文件根目录的相对路径, 对于目录,路径以"/"结尾! 对于文件,路径以文件名结尾!
 *
 * ZipFile 表示一个 ZIP 文件, 它的 entries() 方法能获得ZIP文件中所有的ZipEntry集合
 * ZipEntry的isDirectory 方法判断该ZipEntry是否代表一个目录, getInputStream方法获得ZipEntry 的输入流
 *
 */
public class CompressUtil {
 /**
  *
  * ************************************************* 压缩文件 或者 目录
  *
  * @param baseDirName
  *            压缩的根目录
  * @param fileName
  *            根目录下待压缩的文件或文件夹名
  * @param targetFileName
  *            目标 ZIP 文件
  *
  * 星号 "*" 表示压缩根目录下的全部文件
  *
  */
 public static void zipFile(String baseDirName, String[] fileNames,
   String targetFileName) throws IOException {
  /**
   * 由这个 "压缩的根目录" 文件名路径得到一个 File 对象 并判断这个 File 对象表示的文件是否存在! 是否是一个文件夹!.....
   */
  File baseDir = new File(baseDirName);
  if (!baseDir.exists() || (!baseDir.isDirectory())) {
   System.out.println("压缩失败! 根目录不存在: " + baseDirName);
   return;
  }
  // 得到这个 "压缩的根目录" 的路径.........
  String baseDirPath = baseDir.getAbsolutePath();
  /**
   * 由这个 "目标 ZIP 文件" 文件名得到一个 压缩对象 ZipOutputStream
   */
  File targetFile = new File(targetFileName);
  ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
    targetFile));
  // "*" 表示压缩包括根目录 baseDirName 在内的全部文件 到 targetFileName文件下
  if (fileNames.equals("*")) {
   CompressUtil.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);
    CompressUtil.filesToZip(baseDirPath, files, out);
   }
   
  }
  out.close();
  System.out.println("压缩成功! 目标文件名为: " + targetFileName);
 }

 /**
  *
  * ************************************************* 获取待压缩文件在 ZIP 文件中的 entry
  * 的名字! 即相对于根目录的相对路径名 *************************************************
  *
  */
 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());
 }

 /**
  *
  * ************************************************* 将文件压缩到Zip 输出流
  * *************************************************
  *
  * @author 周宇
  * @throws IOException
  * @Mar 4, 2008 11:12:24 PM
  *
  */
 private static void fileToZip(String baseDirPath, File file,
   ZipOutputStream out) throws IOException {
  //
  FileInputStream in = null;
  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 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 输出流
  * *************************************************
  */
 @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()) {
     // 调用本类的一个静态方法 压缩一个文件
     CompressUtil.fileToZip(baseDirPath, file, out);
    } else {
     /*
      * 这是一个文件夹 所以要再次得到它下面的所有的文件
      * 这里是自己调用自己..............递归..........
      */
     CompressUtil.dirToZip(baseDirPath, file, out);
    }
   }
 }
 /**
  *
  * ************************************************* 将文件目录压缩到Zip 输出流
  * *************************************************
  */
 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);
   ZipEntry entry = new ZipEntry(zipFileName);
   out.putNextEntry(entry);
   out.closeEntry();
  } else {
   // 遍历所有的文件 一个一个地压缩
   for (int i = 0; i < files.length; i++) {
    File file = files[i];
    if (file.isFile()) {
     // 调用本类的一个静态方法 压缩一个文件
     CompressUtil.fileToZip(baseDirPath, file, out);
    } else {
     /*
      * 这是一个文件夹 所以要再次得到它下面的所有的文件
      * 这里是自己调用自己..............递归..........
      */
     CompressUtil.dirToZip(baseDirPath, file, out);
    }
   }
  }
 }

 /**
  *
  * ************************************************* 这个方法是用来 解
  * 压缩文件的.......... *************************************************
  *
  */
 public static void upzipFile(String zipFileName, String targetBaseDirName)
   throws IOException {
  /**
   * 改变 targetBaseDirName 的形式 把 "C:/temp.zip" 变成 "C:/temp.zip/"
   */
  if (!targetBaseDirName.endsWith(File.separator)) {
   targetBaseDirName += File.separator;
  }
  // 根所 ZIP 文件创建 zipFileName 对象
  ZipFile zipFile = new ZipFile(zipFileName);
  ZipEntry entry = null;
  String entryName = null;
  String targetFileName = null;
  // 创建复制缓冲区 1024*4 = 4K
  byte[] buffer = new byte[1024 * 4];
  int bytes_read;
  // 由 ZipFile 对象 得到一个列举集合.......
  Enumeration entrys = zipFile.entries();
  // 遍历这个集合
  while (entrys.hasMoreElements()) {
   // 强制转换成 ZipEntry 对象
   entry = (ZipEntry) entrys.nextElement();
   // 得到 ZipEntry 对象的文件名子;
   entryName = entry.getName();
   /**
    * C:/temp.zip/ + love.txt = C:/temp.zip/love.txt
    */
   targetFileName = targetBaseDirName + entryName;
   // 如果 ZipEntry 是一个目录 则创建这个目录
   if (entry.isDirectory()) {
    new File(targetFileName).mkdirs();
    // 返回 并重新遍历..............
    continue;
   } else {
    /**
     * 如果是一个普通文件 则创建这个文件的父目录以存储本文件
     *
     * 比如 C:/temp.zip/other/love.txt 那么它就先创建 C:/temp.zip/other 文件目录
     * 再往下执行以写入 love.txt 文件对象...........
     *
     * 接着往下执行.............
     */
    new File(targetFileName).getParentFile().mkdirs();
   }
   File targetFile = new File(targetFileName);
   System.out.println("创建文件成功.........."
     + targetFile.getAbsolutePath());
   // 由这个文件对象 得到一个文件写入流对象..........
   FileOutputStream os = new FileOutputStream(targetFile);
   // 由 ZipFile 对象的getInputStream()方法 并传入 ZipEntry 得到读取流对象
   InputStream is = zipFile.getInputStream(entry);
   // 边读边写...........
   while ((bytes_read = is.read(buffer)) != -1) {
    os.write(buffer, 0, bytes_read);
   }
   // 关闭流..........
   os.close();
   is.close();
  }
  System.out.println("@@@@@@@@@解压缩文件成功@@@@@@@@@");
 }

 /**
  *
  * ************************************************* 现在要开始测试了...........<br/><br/>
  *
  * 先要确定这个要压缩的文件的文件全路径(包括文件名子)!<br/><br/>
  *
  * 再确定要压缩的文件名 (它一定要在 要压缩文件 baseDirName 的里面)! 要是给的字符串不是文件名而是 "*" 那么就是要压缩
  * "要压缩的文件" 包括它自己本身在内的所有文件<br/><br/>
  *
  * 然后确定要压缩后的压缩文件全路径(包括文件名子及它的 zip 后缀)!<br/><br/>
  *
  *
  *
  * @param baseDirName
  *            要压缩的文件目录路径名
  *
  * @param fileName
  *            要压缩的文件名 仅仅是一个名子,不是路径! 也可是 "*" 意为压缩本目录中的所有文件)
  *
  * @param zipFileName
  *            压缩完成后的文件路径名称.......
  *
  * @param targetBaseDirName
  *            要 解压缩 后的文件路径名称..........
  *            **************************************************
  *
  * @author 周宇 Mar 5, 2008 11:48:29 PM
  *
  */
 public static void main(String[] args) {
  
  String baseDirName = "C:/station_data";
  
  String[] fileNames = {"bmt20090702vmin.min"};
  // String fileName = "test";
  String zipFileName = "c:/data.zip";
  try {
   CompressUtil.zipFile(baseDirName, fileNames, zipFileName);
  } catch (IOException e) {
   System.out.println(e.getMessage());
   e.printStackTrace();
  }
  /**
   * *************************************************** 解压缩
   * ***************************************************
   */
  String targetBaseDirName = "D:/test";
  try {
   CompressUtil.upzipFile(zipFileName, targetBaseDirName);
  } catch (IOException e) {
   System.out.println(e.getMessage());
   e.printStackTrace();
  }
 }
}

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值