使用ICSharpZipLib将文件夹压缩为zip文件

在我接触Git和SVN之前,我最常用的保存数据的办法就是把文件夹压缩成一个zip文件,添加上时间戳。下面是我在学习C#的文件操作之后做的一个练习,使用开源的ICSharpZipLib来压缩文件夹并保存到指定的目录,还附带简单的日志文件。

关于ICSharpZipLib

ICSharpZipLib是一个开源的应用于.NET平台的开源类库。运用C#语言和这个类库,我们可以很轻松地创建和操作压缩文件,例如:Zip,GZip, Tar and BZip2。

程序界面

放上一张程序的截图:
interface
主要是三个输入内容:源文件夹、压缩包目标文件夹以及单次存档的备份说明。再放上一张压缩好的效果解图:
package

源代码

废话不多说,咱直接上源代码。说实话,使用ICSharpZipLib的博客应该也有很多,但是试了一下好多不能用。下面的这个类是我根据一个印度程序员(英文网站上的,不知道到底是啥名字,但是长得很三哥!)的博客改写的。测试过的哦,亲!

CompressFolderIntoZip.cs

执行将文件压缩的主要代码。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;

namespace Data_Archiving
{
    class CompressFolderIntoZip
    {
        /// <summary>
        /// 用来进行文件夹的压缩,输入参数源文件夹路径和目标文件夹路径即可。
        /// </summary>
        /// <param name="sourceFolderPath"></param>
        /// <param name="destFolderPath"></param>
        /// <returns></returns>
        public static bool CompressFolder(string sourceFolderPath, string destFolderPath)
        {
            try
            {
                //文件名=文件夹名+时间戳+.zip;
                string zipFileName = destFolderPath + "\" +
                    sourceFolderPath.Substring(sourceFolderPath.LastIndexOf('\') + 1) 
                    + "(" + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + ").zip";
                ZipFile zipFile = ZipFile.Create(zipFileName);
                zipFile.BeginUpdate();
                //压缩文件夹时默认采用源文件夹的上一级作为根目录;
                AddFolderToZip(zipFile,
                    sourceFolderPath.Substring(0, sourceFolderPath.LastIndexOf('\')),
                    sourceFolderPath);
                zipFile.CommitUpdate();
                zipFile.Close();
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// 该方法用来实现文件夹及其中文件和子文件夹的递归压缩
        /// ZipFile zipFile=ZipFile.Create(string <zipfilename>)
        /// folderPath是需要压缩的文件夹
        /// root是压缩文件中的根目录,如果folderPath=@"C:Test"而root=@"C:"那么打开压缩文件会先显示一个名为Test的文件夹。如果folderPath=@"C:Test"而root=@"C:Test"那么压缩文件打开会直接显示Test文件夹下所有文件盒子文件夹。
        /// </summary>
        /// <param name="zipFile"></param>
        /// <param name="root"></param>
        /// <param name="folderPath"></param>
        private static void AddFolderToZip(ZipFile zipFile, string root, string folderPath)
        {
            string relativePath = folderPath.Substring(root.Length);
            if (relativePath.Length > 0)
            {
                zipFile.AddDirectory(relativePath);
            }

            foreach (string file in Directory.GetFiles(folderPath))
            {
                relativePath = file.Substring(root.Length);
                zipFile.Add(file, relativePath);
            }

            foreach (string subFolder in Directory.GetDirectories(folderPath))
            {
                AddFolderToZip(zipFile, root, subFolder);
            }
        }
    }
}
Form1.cs

负责校验数据和响应界面上的各种触发事件。

using System;
using System.IO;
using System.Windows.Forms;

namespace Data_Archiving
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void buttonChooseSourceFolder_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == DialogResult.Cancel) return;
            textBoxSourceFolderPath.Text = folderBrowserDialog.SelectedPath;
        }

        private void buttonChooseDestinationFolder_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() != DialogResult.Cancel)
                textBoxDestinationFolderPath.Text = folderBrowserDialog.SelectedPath;
        }

        private void buttonQuit_Click(object sender, EventArgs e)
        {
            Dispose();
        }

        private void buttonExecute_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(textBoxSourceFolderPath.Text)
                || String.IsNullOrEmpty(textBoxDestinationFolderPath.Text)
                || String.IsNullOrEmpty(textBoxDescription.Text))
            {
                MessageBox.Show("输入框中的内容不可为空!");
                return;
            }

            //TODO:用正则表达式校验路径的有效性;

            DirectoryInfo source = new DirectoryInfo(textBoxSourceFolderPath.Text);
            DirectoryInfo destination = new DirectoryInfo(textBoxDestinationFolderPath.Text);

            if (!source.Exists)
            {
                MessageBox.Show("该文件夹不存在!");
                return;
            }
            if (!destination.Exists)
            {
                destination.Create();
            }

            string sourcePath = source.FullName;
            int startPos = sourcePath.LastIndexOf('\');
            string subDirName = destination.FullName + sourcePath.Substring(startPos);
            string logFileName = subDirName + "\Log.txt";

            var subDirInfo = new DirectoryInfo(subDirName);
            if (!subDirInfo.Exists)
            {
                subDirInfo.Create();
            }

            using (var sw = new StreamWriter(logFileName,true))
            {
                try
                {
                    if (new FileInfo(logFileName).Length == 0)
                    {
                        sw.WriteLine("This is the log of data archiving of folder "
                                     + sourcePath);
                        sw.WriteLine("This log is created at {0}",
                            DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
                        sw.WriteLine("=================================================");
                    }

                    sw.WriteLine("Update time: {0}",
                        DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
                    sw.WriteLine("Description:");
                    sw.WriteLine(textBoxDescription.Text);
                    sw.WriteLine("=================================================");
                    sw.Flush();
                    sw.Close();

                    if (!CompressFolderIntoZip.
                        CompressFolder(source.FullName, subDirName))
                    {
                        MessageBox.Show("归档失败!");
                    }

                    textBoxDescription.Text = string.Empty;
                    MessageBox.Show("归档成功!");
                }
                catch (IOException exception)
                {
                    MessageBox.Show(exception.ToString());
                }
            }
        }
    }
}