package com.house365.web.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import org.zeroturnaround.zip.ZipUtil;

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

/**
 * 文件解压缩工具类
 * 
 * @author zhaodeshan
 * @version [v1.0.0, 2015年1月29日]
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public class DecompressUtils {

    /**
     * 解压zip文件
     * 
     * @author zhaodeshan
     * @version [版本号, 2015年1月29日]
     * @param is 文件输入流
     * @param outputDir 要解压到的路径
     * @since [产品/模块版本](可选)
     */
    public static void unzip(InputStream is, String outputDir) {
        ZipUtil.unpack(is, new File(outputDir));
    }

    /**
     * 解压rar文件
     * 
     * @author zhaodeshan
     * @version [版本号, 2015年1月29日]
     * @param is 文件输入流
     * @param outputDir 要解压到的路径
     * @since [产品/模块版本](可选)
     */
    public static void unrar(InputStream is, String fileName, String outputDir) throws Exception {
        File srcFile = new File(fileName);
        stream2File(is, srcFile);
        FileOutputStream fileOut = null;
        Archive rarfile = null;

        try {
            rarfile = new Archive(srcFile);
            FileHeader fh = rarfile.nextFileHeader();
            while (fh != null) {
                String entrypath = "";
                if (fh.isUnicode()) {// 解决中文乱码
                    entrypath = fh.getFileNameW().trim();
                } else {
                    entrypath = fh.getFileNameString().trim();
                }
                entrypath = entrypath.replaceAll("\\\\", "/");

                File file = new File(outputDir + entrypath);

                if (fh.isDirectory()) {
                    file.mkdirs();
                } else {
                    File parent = file.getParentFile();
                    if (parent != null && !parent.exists()) {
                        parent.mkdirs();
                    }
                    fileOut = new FileOutputStream(file);
                    rarfile.extractFile(fh, fileOut);
                }
                fh = rarfile.nextFileHeader();
            }
        } catch (Exception e) {
            throw e;
        } finally {
            if (fileOut != null) {
                try {
                    fileOut.close();
                    fileOut = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (rarfile != null) {
                try {
                    rarfile.close();
                    rarfile = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
            srcFile.delete();
        }
    }

    /**
     * 解压zip或rar文件
     * 
     * @author zhaodeshan
     * @version [版本号, 2015年1月29日]
     * @param is 文件输入流
     * @param fileName 要解压的文件名
     * @param outputDir 要解压到的路径
     * @since [产品/模块版本](可选)
     */
    public static void deCompress(InputStream is, String fileName, String outputDir) throws Exception {
        // 保证文件夹路径最后是"/"或者"\"
        char lastChar = outputDir.charAt(outputDir.length() - 1);
        if (lastChar != '/' && lastChar != '\\') {
            outputDir += File.separator;
        }
        // 根据类型，进行相应的解压缩
        String type = fileName.substring(fileName.lastIndexOf(".") + 1);
        if ("zip".equals(type)) {
            unzip(is, outputDir);
        } else if ("rar".equals(type)) {
            unrar(is, fileName, outputDir);
        } else {
            throw new Exception("只支持zip和rar格式的压缩包！");
        }
    }

    /**
     * 将输入流存储到文件中
     * @author zhaodeshan
     * @version [版本号, 2015年1月29日]
     * @param is 文件输入流
     * @param file 文件
     * @since [产品/模块版本](可选)
     */
    public static void stream2File(InputStream is, File file) {
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                    os = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
            if (is != null) {
                try {
                    is.close();
                    is = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        InputStream stream = new FileInputStream("D:/开源库/示例.rar");
        deCompress(stream, "示例.rar", "D:/开源库/");
    }

}
