package cn.hmsoft.helper;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/*************************
 * 
 * @note zip文件处理
 * @author revisit@126.com
 * @Company: www.hmsoft.cn
 * @create 2018年1月22日 下午9:39:25
 * @version 4.0.0
 */
public class ZipHelper {
	/**************************
	 * 将zip文件解压到指定目录
	 * 
	 * @param file zip文件
	 * @param targetFileDir 解压到的目录
	 */
	public static void unzip(File file, String targetFileDir) {
		// 1.判断压缩文件是否存在，以及里面的内容是否为空
		ZipFile zipFile = null;
		// 2.开始解压ZIP压缩文件的处理
		byte[] buf = new byte[1024 * 1024];
		int readSize = -1;
		ZipInputStream zis = null;
		FileOutputStream fos = null;
		try {
			// 检查是否是zip文件
			zipFile = new ZipFile(file);
			zipFile.close();
			// 判断目标目录是否存在，不存在则创建
			File newdir = new File(targetFileDir);
			if (false == newdir.exists()) {
				newdir.mkdirs();
				newdir = null;
			}
			zis = new ZipInputStream(new FileInputStream(file),Charset.forName("GBK"));
			ZipEntry zipEntry = zis.getNextEntry();
			// 开始对压缩包内文件进行处理
			while (null != zipEntry) {
				String zipEntryName = zipEntry.getName().replace('\\', '/');
				// 判断zipEntry是否为目录，如果是，则创建
				if (zipEntry.isDirectory()) {
					int indexNumber = zipEntryName.lastIndexOf('/');
					File entryDirs = new File(targetFileDir + "/"
							+ zipEntryName.substring(0, indexNumber));
					entryDirs.mkdirs();
					entryDirs = null;
				} else {
					try {
						fos = new FileOutputStream(targetFileDir + "/"
								+ zipEntryName);
						while ((readSize = zis.read(buf, 0, 1024 * 1024)) != -1) {
							fos.write(buf, 0, readSize);
						}
					} catch (Exception e) {
						e.printStackTrace();
						throw new RuntimeException(e.getCause());
					} finally {
						try {
							if (null != fos) {
								fos.close();
							}
						} catch (IOException e) {
							e.printStackTrace();
							throw new RuntimeException(e.getCause());
						}
					}
				}
				zipEntry = zis.getNextEntry();
			}
		} catch (ZipException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getCause());
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getCause());
		} finally {
			try {
				if (null != zis) {
					zis.close();
				}
				if (null != fos) {
					fos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException(e.getCause());
			}
		}
	}

	/************************
	 * 压缩一个文件
	 * 
	 * @param srcPathName
	 * @param zipFile
	 */
	public static void compress(String srcPathName, File zipFile) {
		File file = new File(srcPathName);
		if (!file.exists())
			throw new RuntimeException(srcPathName + "不存在！");
		try {
			FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
			CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
					new CRC32());
			ZipOutputStream out = new ZipOutputStream(cos);
			String basedir = "";
			compress(file, out, basedir);
			out.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private static void compress(File file, ZipOutputStream out, String basedir) {
		/* 判断是目录还是文件 */
		if (file.isDirectory()) {
			compressDirectory(file, out, basedir);
		} else {
			compressFile(file, out, basedir);
		}
	}

	/** 压缩一个目录 */
	public static void compressDirectory(File dir, ZipOutputStream out,
			String basedir) {
		if (!dir.exists())
			return;

		File[] files = dir.listFiles();
		for (int i = 0; i < files.length; i++) {
			/* 递归 */
			compress(files[i], out, basedir + dir.getName() + "/");
		}
	}

	/** 压缩多个文件 */
	public static void compress(List<File> array, File zipFile) {

		try {
			FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
			CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
					new CRC32());
			ZipOutputStream out = new ZipOutputStream(cos);
			String basedir = "";
			for (int i = 0; i < array.size(); i++) {
				/* 递归 */
				compress(array.get(i), out, basedir);
			}
			out.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	}

	/** 压缩一个文件 */
	public static void compressFile(File file, ZipOutputStream out,
			String basedir) {
		if (!file.exists()) {
			return;
		}
		try {
			BufferedInputStream bis = new BufferedInputStream(
					new FileInputStream(file));
			ZipEntry entry = new ZipEntry(basedir + file.getName());
			out.putNextEntry(entry);
			int count;
			byte data[] = new byte[1024];
			while ((count = bis.read(data, 0, 1024)) != -1) {
				out.write(data, 0, count);
			}
			bis.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}
