package decompress;      
         
    import java.io.File;      
    import java.io.FileOutputStream;      
         
    import org.apache.tools.ant.Project;      
    import org.apache.tools.ant.taskdefs.Expand;      
         
    import de.innosystec.unrar.Archive;      
    import de.innosystec.unrar.rarfile.FileHeader;      
         
    public class DeCompressUtil {      
       /**    
        * 解压zip格式压缩包    
        * 对应的是ant.jar    
        */     
       private static void unzip(String sourceZip,String destDir) throws Exception{      
           try{      
               Project p = new Project();      
               Expand e = new Expand();      
               e.setProject(p);      
               e.setSrc(new File(sourceZip));      
               e.setOverwrite(false);      
               e.setDest(new File(destDir));      
               /*    
               ant下的zip工具默认压缩编码为UTF-8编码,    
               而winRAR软件压缩是用的windows默认的GBK或者GB2312编码    
               所以解压缩时要制定编码格式    
               */     
               e.setEncoding("gbk");      
               e.execute();      
           }catch(Exception e){      
               throw e;      
           }      
       }      
       /**    
        * 解压rar格式压缩包。    
        * 对应的是java-unrar-0.3.jar,但是java-unrar-0.3.jar又会用到commons-logging-1.1.1.jar    
        */     
       private static void unrar(String sourceRar,String destDir) throws Exception{      
           Archive a = null;      
           FileOutputStream fos = null;      
           try{      
               a = new Archive(new File(sourceRar));      
               FileHeader fh = a.nextFileHeader();      
               while(fh!=null){      
                   if(!fh.isDirectory()){      
                       //1 根据不同的操作系统拿到相应的 destDirName 和 destFileName      
                       String compressFileName = fh.getFileNameString().trim();      
                       String destFileName = "";      
                       String destDirName = "";      
                       //非windows系统      
                       if(File.separator.equals("/")){      
                           destFileName = destDir + compressFileName.replaceAll("\\\\", "/");      
                           destDirName = destFileName.substring(0, destFileName.lastIndexOf("/"));      
                       //windows系统       
                       }else{      
                           destFileName = destDir + compressFileName.replaceAll("/", "\\\\");      
                           destDirName = destFileName.substring(0, destFileName.lastIndexOf("\\"));      
                       }      
                       //2创建文件夹      
                       File dir = new File(destDirName);      
                       if(!dir.exists()||!dir.isDirectory()){      
                           dir.mkdirs();      
                       }      
                       //3解压缩文件      
                       fos = new FileOutputStream(new File(destFileName));      
                       a.extractFile(fh, fos);      
                       fos.close();      
                       fos = null;      
                   }      
                   fh = a.nextFileHeader();      
               }      
               a.close();      
               a = null;      
           }catch(Exception e){      
               throw e;      
           }finally{      
               if(fos!=null){      
                   try{fos.close();fos=null;}catch(Exception e){e.printStackTrace();}      
               }      
               if(a!=null){      
                   try{a.close();a=null;}catch(Exception e){e.printStackTrace();}      
               }      
           }      
       }      
       /**    
        * 解压缩    
        */     
       public static void deCompress(String sourceFile,String destDir) throws Exception{      
           //保证文件夹路径最后是"/"或者"\"      
           char lastChar = destDir.charAt(destDir.length()-1);      
           if(lastChar!='/'&&lastChar!='\\'){      
               destDir += File.separator;      
           }      
           //根据类型,进行相应的解压缩      
           String type = sourceFile.substring(sourceFile.lastIndexOf(".")+1);      
           if(type.equals("zip")){      
               DeCompressUtil.unzip(sourceFile, destDir);      
            }else if(type.equals("rar")){      
                DeCompressUtil.unrar(sourceFile, destDir);      
            }else{      
                throw new Exception("只支持zip和rar格式的压缩包!");      
            }      
        }      
    }    

 

RAR压缩算法是不公开的,所以这方面的开源项目不多

幸好有一个叫unrar的开源项目支持RAR的解压,但不能压缩RAR文件

不过,直接使用unrar却不能支持带密码的RAR文件解压,经过多方查找,终于在Google Code上面找到一个支持密码的unrar版本,下载地址:http://code.google.com/p/java-unrar/

该项目依赖Jar包:

commons-logging.jar  比较常用,可以到Apache官网下载

gnu-crypto.jar  可以在http://www.gnu.org/software/gnu-crypto/下载

下面是一个简单的解压示例:

package com.reyo.demo.rar;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.io.IOUtils;

import de.innosystec.unrar.Archive;
import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.rarfile.FileHeader;

/**
 * RAR格式压缩文件解压工具类
 * 不支持RAR格式压缩
 * 支持中文,支持RAR压缩文件密码
 * 依赖jar包
 * commons-io.jar
 * commons-logging.jar
 * java-unrar-decryption-supported.jar
 * gnu-crypto.jar
 *
 * @author ninemax
 */
public class RarDecompressionUtil {
 
 public static final String SEPARATOR = File.separator;
 
 // =============================== RAR Format ================================
 /**
  * 解压指定RAR文件到当前文件夹
  * @param srcRar 指定解压
  *  @param password 压缩文件时设定的密码
  * @throws IOException
  */
 public static void unrar(String srcRar, String password) throws IOException {
  unrar(srcRar, null, password);
 }
 
 /**
  * 解压指定的RAR压缩文件到指定的目录中
  * @param srcRar 指定的RAR压缩文件
  * @param destPath 指定解压到的目录
  *  @param password 压缩文件时设定的密码
  * @throws IOException
  */
 public static void unrar(String srcRar, String destPath, String password) throws IOException {
  File srcFile = new File(srcRar);
  if (!srcFile.exists()) {
   return;
  }
  if (null == destPath || destPath.length() == 0) {
   unrar(srcFile, srcFile.getParent(), password);
   return;
  }
  unrar(srcFile,destPath, password);
 }
 
 /**
  * 解压指定RAR文件到当前文件夹
  * @param srcRarFile 解压文件
  *  @param password 压缩文件时设定的密码
  * @throws IOException
  */
 public static void unrar(File srcRarFile, String password) throws IOException {
  if (null == srcRarFile || !srcRarFile.exists()) {
   throw new IOException("指定文件不存在.");
  }
  unrar(srcRarFile, srcRarFile.getParent(),password);
 }
 
 /**
  * 解压指定RAR文件到指定的路径
  * @param srcRarFile 需要解压RAR文件
  * @param destPath 指定解压路径
  * @param password 压缩文件时设定的密码
  * @throws IOException
  */
 public static void unrar(File srcRarFile, String destPath, String password) throws IOException {
  if (null == srcRarFile || !srcRarFile.exists()) {
   throw new IOException("指定压缩文件不存在.");
  }
  if (!destPath.endsWith(SEPARATOR)) {
   destPath += SEPARATOR;
  }
  Archive archive = null;
  OutputStream unOut = null;
  try {
   archive = new Archive(srcRarFile, password, false);
   FileHeader fileHeader = archive.nextFileHeader();
   while(null != fileHeader) {
    if (!fileHeader.isDirectory()) {
     // 1 根据不同的操作系统拿到相应的 destDirName 和 destFileName
     String destFileName = "";
     String destDirName = "";
     if (SEPARATOR.equals("/")) {  // 非windows系统
      destFileName = (destPath + fileHeader.getFileNameW()).replaceAll("\\\\", "/");
      destDirName = destFileName.substring(0, destFileName.lastIndexOf("/"));
     } else {  // windows系统
      destFileName = (destPath + fileHeader.getFileNameW()).replaceAll("/", "\\\\");
      destDirName = destFileName.substring(0, destFileName.lastIndexOf("\\"));
     }
     // 2创建文件夹
     File dir = new File(destDirName);
     if (!dir.exists() || !dir.isDirectory()) {
      dir.mkdirs();
     }
     // 抽取压缩文件
     unOut = new FileOutputStream(new File(destFileName));
     archive.extractFile(fileHeader, unOut);
     unOut.flush();
     unOut.close();
    }
    fileHeader = archive.nextFileHeader();
   }
   archive.close();
  } catch (RarException e) {
   e.printStackTrace();
  } finally {
   IOUtils.closeQuietly(unOut);
  }
 }
}

发布评论

分享到:

IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

判断一个枚举值是否属于某个枚举类详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。