背景

在实际项目开发过程中有一个功能需要对文件目录进行压缩,于是上网查阅相关资料。在众多的程序集中,SharpZipLib是呼声最高的,同样还有一个程序集是ICSharpCode.SharpZipLib.dll,该程序集与前一个程序集是不一样的,读者要做好区分,不过区不区分也不要紧,因为如果是“懒癌”患者,那么这两个都会用不到,因为需要利用这两个程序集封装自己的ZIPHelper(zip帮助类),因此不怎么推荐。除了上面所述原因,还有一个主要原因是:在我的项目(.net core5.0)中使用不了!也可能是我的使用方法不对造成的,总之就是给我的第一感觉是:不好用。因此再翻阅资料发现一个系统程序集自带的方法可以实现文件的压缩,下面附上详细的用法以及注意事项。

存在于System.IO.Compression的ZipFile.CreateFromDirectory()方法

看到System.IO开头的命名空间时,我们就应该意识到这是框架自带的方法,所以不用引入第三方包。使用方法很简单,点击此处可跳转至官方中文文档

public static void CreateFromDirectory (string sourceDirectoryName, string destinationArchiveFileName);

参数
sourceDirectoryName String
到要存档的目录的路径,指定为相对路径或绝对路径。 相对路径被解释为相对于当前工作目录。
destinationArchiveFileName String
要生成的存档路径,指定为相对路径或绝对路径。 相对路径被解释为相对于当前工作目录。

注意事项

  • 参数destinationArchiveFileName需要包含文件后缀名.zip
  • 两个参数不能指向同一个文件目录,即不能够将压缩后得到的文件放在原目录下,需要保存在其他的路径下,否则将会报如下错误:

    The process cannot access the file ‘xxx/xxx/xxx.zip’because it is being used by another process.

    该报错信息提示线程无法获取xxx文件,该文件被其他线程占用

应用案例

using System;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace ExportHTML.Tools
{
    /// <summary>
    /// 压缩文件类
    /// </summary>
    public class CompressionFolder
    {
        public CompressionFolder()
        {
        }
        /// <summary>
        /// 压缩文件目录的方法
        /// </summary>
        /// <param name="guid">由于之前是利用guid来生成目录以及文件,所以这里同样使用guid来进行指向</param>
        public void zipFolder(string guid)
        {
            string zipPath = AppContext.BaseDirectory + "/zip"; // 保存zip的目录路径
            if (!File.Exists(zipPath)) // 判断是否存在该文件目录
            {
                Directory.CreateDirectory(zipPath); //如果没有该目录则创建目录
            }
            string reportFolderPath = "{basePath}/reports/{guid}";  //报告目录
            StringBuilder reportFilePathStr = new StringBuilder(reportFolderPath);
            reportFilePathStr.Replace("{basePath}", AppContext.BaseDirectory);
            reportFilePathStr.Replace("{guid}", guid);
            
            string zipFolderPath = "{basePath}/zip/{guid}.zip";  //压缩文件目录
            StringBuilder zipFilePathStr = new StringBuilder(zipFolderPath);
            zipFilePathStr.Replace("{basePath}", AppContext.BaseDirectory);
            zipFilePathStr.Replace("{guid}", guid);

            ZipFile.CreateFromDirectory(reportFilePathStr.ToString(), zipFilePathStr.ToString()); // 压缩文件
        }
    }
}

总结

这个功能实现过程中,网上资料大部分显示的是第三方包的实现方法,但是在我这行不通,翻阅了较长一段时间的资料之后才发现有这么一个方法。在使用该静态方法的过程中发现一个报错点(注意事项第二点),该点查阅资料之后大部分是说文件流未关闭,但是查看自己的源代码发现所有文件流都已关闭,仍然行不通。在尝试几个方法后还是到互联网上查阅相关资料,最终在国外的一个论坛中找到和自己一样报错的帖子,在回复中就有相应的解决办法,即注意事项中的解决方法。