java压缩与解压缩

jopen 10年前

主要用到apache的ant.jar,也可用jdk的相关类,但会有中文乱码问题。最重要的俩类是ZipFile和ZipEntry,前者将zip文件转为java对象,后者将zip文件中的条目文件转为java对象。
核心代码如下:

压缩代码:

ZipOutputStream zipOs = new ZipOutputStream(fos);  ZipEntry zipEntry = new ZipEntry("entryName");  zipOs.putNextEntry(zipEntry);

解压缩代码:

Enumeration<ZipEntry> entries = zipFile.getEntries();  ZipEntry zipEntry = entries.nextElement();  InputStream ins = zipFile.getInputStream(zipEntry);

需要注意的地方:

针对空文件夹需要特殊处理,需要往Entry中放入”/“+文件夹名+“/“项

zipOs.putNextEntry("/");

详细点的练习:

/**   * 测试文件压缩与解压缩   *   */  public class TestZip {        public static void main(String[] args) {          //-->压缩单个文件          zipSingleFileOrFolder("D:\\BIZFLOW\\src\\tst\\新建文本文档.zip", "D:\\BIZFLOW\\src\\tst\\新建文本文档.txt");          //-->压缩文件夹          //zipSingleFileOrFolder("D:\\BIZFLOW\\src\\tst.zip", "D:\\BIZFLOW\\src\\tst");          //-->压缩多个文件(不指定压缩文件保存路径)          //zipMultiFiles("","D:\\BIZFLOW\\src\\tst\\新建文本文档.txt","D:\\BIZFLOW\\src\\tst\\新建文本文档 - 副本.txt");          //-->压缩多个文件(指定压缩文件保存路径)          //zipMultiFiles("D:\\BIZFLOW\\src\\tst\\新建.zip","D:\\BIZFLOW\\src\\tst\\新建文本文档.txt","D:\\BIZFLOW\\src\\tst\\新建文本文档 - 副本.txt");          //-->解压缩文件          //unzipFile("D:\\BIZFLOW\\src\\tst\\新建", "D:\\BIZFLOW\\src\\tst\\新建文本文档.txt等.zip");      }        /**       * 压缩单个文件/文件夹       * @param destPath 压缩文件保存路径(为空串/null时默认压缩路径:待压缩文件所在目录,压缩文件名为待压缩文件/文件夹名+“等.zip”)       * @param srcPath 待压缩的文件路径       */      public static void zipSingleFileOrFolder(String destPath, String srcPath) {          if(StringUtils.isBlank(srcPath)) {              throw new RuntimeException("待压缩文件夹不可为空!");          }          if(StringUtils.isNotBlank(destPath) && !destPath.endsWith(".zip")) {              throw new RuntimeException("保存文件名应以.zip结尾!");          }          File file = new File(srcPath);          if(!file.exists()) {              throw new RuntimeException("路径'"+srcPath+"'下未找到文件");          }          if(file.isDirectory()) {              //压缩文件夹              zipFolder(destPath, srcPath);          } else {              //压缩单个文件              zipFile(destPath, srcPath);           }      }        /**       * 压缩多个文件       * @param destPath 压缩文件保存路径(为空串/null时默认压缩路径:待压缩文件所在目录,压缩文件名为第一个待压缩文件名+“等.zip”)       * @param srcPaths 待压缩文件路径集合       */      public static void zipMultiFiles(String destPath, String...srcPaths) {          if(srcPaths==null || srcPaths.length==0) {              throw new RuntimeException("待压缩文件夹不可为空!");          }          if(StringUtils.isNotBlank(destPath) && !destPath.endsWith(".zip")) {              throw new RuntimeException("保存文件名应以.zip结尾!");          }          zipFiles(destPath, srcPaths);      }        /**       * 解压缩文件       * @param destPath 解压缩路径(为空串/null时默认解压缩路径:压缩文件所在目录)       * @param zipPath 压缩文件路径       */      public static void unzipFile(String destPath, String zipPath) {          if(StringUtils.isBlank(zipPath)) {              throw new RuntimeException("压缩文件路径不可为空!");          }          if(!zipPath.endsWith(".zip")) {              throw new RuntimeException("保存文件名应以.zip结尾!");          }          File file = new File(zipPath);          if(StringUtils.isBlank(destPath)) {              destPath = getUnzipBasePath(file);          }          if(!file.exists()) {              throw new RuntimeException("路径'"+zipPath+"'下未找到文件");          }          ZipFile zipFile;          int len;          byte[] buff = new byte[1024];          try {              zipFile = new ZipFile(zipPath);              //获取压缩文件中所有条目              Enumeration<ZipEntry> entries = zipFile.getEntries();              if(entries!=null) {                  while(entries.hasMoreElements()) {                      //压缩文件条目转为文件或文件夹                      ZipEntry zipEntry = entries.nextElement();                      //获取输入流                      InputStream ins = zipFile.getInputStream(zipEntry);                      BufferedInputStream bis = new BufferedInputStream(ins);                      File unzipFile = new File(destPath+File.separator+zipEntry.getName());                      if(zipEntry.isDirectory()) {                          unzipFile.mkdirs();                          continue;                      }                         File pf = unzipFile.getParentFile();                      if(pf!=null && !pf.exists()) {                          pf.mkdirs();                      }                      unzipFile.createNewFile();                      FileOutputStream fos = new FileOutputStream(unzipFile);                      BufferedOutputStream bos = new BufferedOutputStream(fos);                      //输出流写文件                      while((len=bis.read(buff, 0, 1024))!=-1) {                          bos.write(buff, 0, len);                      }                      bos.flush();                      fos.close();                      bos.close();                  }              }          } catch (IOException e) {              e.printStackTrace();              throw new RuntimeException();          }        }        /**       * 获取解压缩文件基路径       * @param zipPath       * @return        */      private static String getUnzipBasePath(File zipPath) {          return zipPath.getParentFile().getAbsolutePath();      }        /**       * 压缩单个文件       * @param destPath 压缩文件保存路径       * @param srcPath 待压缩文件路径       */      private static void zipFile(String destPath, String srcPath) {          zipFiles(destPath, srcPath);      }      /**       * 压缩多个文件       * @param srcPath       * @param zipPath       */      private static void zipFiles(String destPath, String...srcPaths) {          if(StringUtils.isBlank(destPath)) {              File srcFile0 = new File(srcPaths[0]);              destPath = srcFile0.getParentFile().getAbsolutePath()+File.separator+srcFile0.getName()+"等.zip";          }          File zipFile = new File(destPath);          FileOutputStream fos = null;          try {              zipFile.createNewFile();              zipFile.mkdirs();              fos = new FileOutputStream(zipFile);          } catch (IOException e) {              e.printStackTrace();              throw new RuntimeException();          }          //获取输出流          ZipOutputStream zipOs = new ZipOutputStream(fos);          //循环将多个文件转为压缩文件条目          for(String srcPath : srcPaths) {              if(StringUtils.isBlank(srcPath)) {                  throw new RuntimeException("待压缩文件路径不可为空!");              }              File srcFile = new File(srcPath);              try {                  ZipEntry zipEntry = new ZipEntry(srcFile.getName());                  zipOs.putNextEntry(zipEntry);                  //获取输入流                  FileInputStream fis = new FileInputStream(srcFile);                  int len;                  byte[] buff = new byte[1024];                  //输入/输出流对拷                  while((len=fis.read(buff))!=-1) {                      zipOs.write(buff, 0, len);                  }                  fis.close();              } catch (FileNotFoundException e) {                  e.printStackTrace();                  throw new RuntimeException();              } catch (IOException e) {                  e.printStackTrace();                  throw new RuntimeException();              }          }          try {              zipOs.flush();              zipOs.close();          } catch (IOException e) {              e.printStackTrace();              throw new RuntimeException();          }      }        /**       * 压缩文件夹       * @param destPath 压缩文件保存路径       * @param srcPath 待压缩文件夹路径       */      private static void zipFolder(String destPath, String srcPath) {          File srcFile = new File(srcPath);          //如压缩文件保存路径为空,则默认保存路径          if(StringUtils.isBlank(destPath)) {              destPath = srcFile.getParent()+File.separator+srcFile.getName()+".zip";          }          FileOutputStream fos = null;          ZipOutputStream zipOs = null;          try {              fos = new FileOutputStream(destPath);              zipOs = new ZipOutputStream(fos);              //递归往压缩文件中添加文件夹条目              zipFolder(srcFile, srcFile, zipOs);              zipOs.close();          } catch (FileNotFoundException e) {              e.printStackTrace();              throw new RuntimeException();          } catch (IOException e) {              e.printStackTrace();              throw new RuntimeException();          }      }        /**       * 递归往压缩文件中添加文件夹条目       * @param srcFile 待压缩文件夹路径       * @param baseFile        * @param zipOs       */      private static void zipFolder(File srcFile, File baseFile, ZipOutputStream zipOs) {          int len;          byte[] buff = new byte[1024];          if(srcFile.isDirectory()) {              //针对空文件夹需要特殊处理,需要往Entry中放入"/"+文件夹名+"/"项              try {                  zipOs.putNextEntry(new ZipEntry(srcFile.getAbsolutePath().replaceFirst(baseFile.getParentFile().getAbsolutePath().replaceAll("\\\\", "\\\\\\\\"), "")+"/"));                  zipOs.closeEntry();              } catch (IOException e) {                  e.printStackTrace();                  throw new RuntimeException();              }              //获取当前文件夹下文件列表              File[] fileLists = srcFile.listFiles();              if(fileLists!=null && fileLists.length>0) {                  for (int i = 0; i < fileLists.length; i++) {                      //递归往压缩文件中添加文件夹条目                      zipFolder(fileLists[i], baseFile, zipOs);                  }              }          } else {              //文件处理比较简单,直接放入Entry              try {                  FileInputStream fis = new FileInputStream(srcFile);                  zipOs.putNextEntry(new ZipEntry(getRelativePath(baseFile.getAbsolutePath(), srcFile)));                  while((len=fis.read(buff))!=-1) {                      zipOs.write(buff, 0, len);                  }                  zipOs.closeEntry();                  fis.close();              } catch (IOException e) {                  e.printStackTrace();                  throw new RuntimeException();              }          }      }        /**       * 获取相对基路径的相对路径       * @param basePath       * @param file       * @return       */      private static String getRelativePath(String basePath, File file) {          if(!basePath.equalsIgnoreCase(file.getAbsolutePath())) {              return getRelativePath(basePath, file.getParentFile())+File.separator+file.getName();          } else {              return file.getName();          }      }    }