using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
namespace Test{
    /// <summary>
    /// 压缩
    /// </summary>
    public class Compress
    {
        /// <summary>
        /// zip路径
        /// </summary>
        public class ZipPath
        {
            /// <summary>
            /// 是否是文件
            /// </summary>
            public bool IsFile { get; set; }
            /// <summary>
            /// zip中路径
            /// </summary>
            public string Path { get; set; }
            /// <summary>
            /// 绝对路径
            /// </summary>
            public string FullPath{get;set;}
        }
        /// <summary>
        /// 递归获取文件目录
        /// 王洪岐 2011-11-22
        /// </summary>
        /// <param name="arrPath"></param>
        /// <param name="listPath"></param>
        /// <param name="strMainPath"></param>
        public static void GetFiles(string[] arrPath, List<ZipPath> listPath, string strMainPath)
        {
            foreach (string strN in arrPath)
            {
                List<string> fileList = Directory.GetFiles(strN).ToList();
                string[] arrDir=Directory.GetDirectories(strN);
                if (fileList.Count == 0 && arrDir.Length == 0) listPath.Add(new ZipPath { IsFile = false, Path = strN.Substring(strMainPath.Length + 1) + "\\", FullPath = strN });
                for (int i = 0; i < fileList.Count; i++)
                {
                    listPath.Add(new ZipPath { IsFile = true, Path = fileList[i].Substring(strMainPath.Length + 1), FullPath = fileList[i] });
                }
                GetFiles(arrDir, listPath, strMainPath);
            }
        }
        /// <summary>
        /// zip递归压缩 
        /// 王洪岐 2011-11-22
        /// 例:Compress.ZipCompress(new string[] { @"E:\TrainUpdate\ViewWeb\File\SrcSamples\doc", @"E:\素材\icon", @"E:\重要资料\C#\SharpZipLib\压缩sample.cs" }, Server.MapPath("~/File/a.zip"));
        /// </summary>
        /// <param name="path">源文件夹路径</param>
        /// <param name="topath">目标文件路径</param>
        /// <param name="FileName">从源文件夹中指定某文件</param>
        /// <returns>-1=文件不存在,0=未知错误,1=成功</returns>
        public static int ZipCompress(string[] arrPath, string topath)
        {
            try
            {
                List<ZipPath> listPath = new List<ZipPath>();
                foreach (string strN in arrPath)
                {
                    string strMainPath = string.Empty;
                    //文件夹不存在
                    if (!Directory.Exists(strN) && !File.Exists(strN))
                    {
                        return -1;
                    }
                    if (string.IsNullOrEmpty(strMainPath))
                    {
                        strMainPath = Path.GetDirectoryName(strN);
                    }
                    //是文件
                    if (File.Exists(strN))
                    {
                        listPath.Add(new ZipPath { IsFile = true, Path = strN.Substring(strMainPath.Length + 1), FullPath = strN });
                    }
                    else
                    {
                        List<string> fileList = Directory.GetFiles(strN).ToList();
                        if (fileList.Count == 0) listPath.Add(new ZipPath { IsFile = false, Path = strN.Substring(strMainPath.Length + 1), FullPath = strN });
                        for (int i = 0; i < fileList.Count; i++)
                        {
                            listPath.Add(new ZipPath { IsFile = true, Path = fileList[i].Substring(strMainPath.Length + 1), FullPath = fileList[i] });
                        }
                        GetFiles(Directory.GetDirectories(strN), listPath, strMainPath);
                    }
                }
                using (ZipOutputStream s = new ZipOutputStream(File.Create(topath)))
                {
                    s.SetLevel(9); // 0 - store only to 9 - means best compression
                    byte[] buffer = new byte[4096];
                    foreach (ZipPath file in listPath)
                    {
                        if (file.IsFile)//是文件
                        {
                            ZipEntry entry = new ZipEntry(file.Path);
                            entry.DateTime = DateTime.Now;
                            s.PutNextEntry(entry);
                            using (FileStream fs = File.OpenRead(file.FullPath))
                            {
                                int sourceBytes;
                                do
                                {
                                    sourceBytes = fs.Read(buffer, 0, buffer.Length);
                                    s.Write(buffer, 0, sourceBytes);
                                } while (sourceBytes > 0);
                            }
                        }
                        else
                        {
                            ZipEntry entry = new ZipEntry(file.Path);
                            s.PutNextEntry(entry);
                        }
                    }
                    s.Finish();
                    s.Close();
                }
                return 1;
            }
            catch
            {
                return 0;
            }
        }
        /// <summary>
        /// 解压缩
        /// 王洪岐
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="topath"></param>
        /// <returns></returns>
        public static int ZipUnCompress(string filePath,string topath)
        {
            //文件不存在
            if (!File.Exists(filePath))
            {
                return -1;
            }
            try
            {
                using (ZipInputStream s = new ZipInputStream(File.OpenRead(filePath)))
                {
                    ZipEntry theEntry;
                    while ((theEntry = s.GetNextEntry()) != null)
                    {
                        string directoryName = Path.GetDirectoryName(theEntry.Name);
                        string fileName = Path.GetFileName(theEntry.Name);
                        // create directory
                        if (directoryName.Length > 0)
                        {
                            Directory.CreateDirectory(topath + directoryName);
                        }
                        else if (!Directory.Exists(topath))
                        {
                            Directory.CreateDirectory(topath);
                        }
                        if (fileName != String.Empty)
                        {
                            using (FileStream streamWriter = File.Create(topath + theEntry.Name))
                            {
                                int size = 2048;
                                byte[] data = new byte[2048];
                                while (true)
                                {
                                    size = s.Read(data, 0, data.Length);
                                    if (size > 0)
                                    {
                                        streamWriter.Write(data, 0, size);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                return 1;
            }
            catch
            {
                return 0;
            }
        }
    }
}