如何创建只包含特定扩展名的zip归档文件

本文关键字:扩展名 zip 归档文件 包含特 何创建 创建 | 更新日期: 2023-09-27 18:09:56

我需要创建一个zip存档,它应该只包含某些扩展名的文件,但我需要保存原始目录的结构。

例如,我有一个结构如下的目录:
dir'
  sub_dir1'
    1.exe
  sub_dir_2'
    1.txt
    1.exe
  1.txt
  1.bat

和我需要得到一个档案与以下结构(只有。exe和。bat文件):

dir'
  sub_dir1'
    1.exe
  sub_dir_2'
    1.exe
  1.bat

我知道如何通过目录找到这些文件。getfile方法:

var ext = new List<string> {".exe", ".bat"};
var myFiles = Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories)
     .Where(s => ext.Any(e => s.EndsWith(e));

但是我不知道如何保存存档的结构。

我怎样才能达到这样的行为?

如何创建只包含特定扩展名的zip归档文件

您可以从所有子目录中获取所有扩展名为。exe和。bat的文件,例如:

IList<FileInfo> info = null;    
DirectoryInfo dirInfo = new DirectoryInfo(path);
info = dirInfo
       .GetFiles("*.*", SearchOption.AllDirectories)
       .Where( f => f.Extension
                    .Equals(".exe", StringComparison.CurrentCultureIgnoreCase)
                 || f.Extension
                    .Equals(".bat", StringComparison.CurrentCultureIgnoreCase)
        )
        .ToList()
        ;

然后基于这个FileInfo列表,你可以创建你的zip和文件夹结构。您可以在这里找到文件信息的详细信息

System.IO.Directory.GetFiles("C:''temp", "*.exe", SearchOption.AllDirectories);将返回一个包含完整文件路径的数组,如:

[C:'temp'dir1'app1.exe]
[C:'temp'dir2'subdir1'app2.exe]
[C:'temp'dir3'subdir2'subdir3'app3.exe]

因此,使用ZipArchive将这些文件放入zip容器中不会有任何麻烦。因为此方法将在zip中创建相同的目录结构。但是,您应该删除开头的C:'

我相信这个非常好的教程将帮助您做到这一点。

如果你想在目标zip中保持空文件夹,也许你必须使用ZipArchive.CreateEntry方法来做。在此演示中,作者仅使用ZipArchive. CreateEntryFromFile方法从文件路径归档文件。

您也可以使用DotNetZip库来解决您的问题。例如,下面的代码片段可以帮助您。使用CreateZip()方法。简而言之,您应该找到用于写入存档GetFileNames()的文件,并使用CreateZipFromFileNames()创建zip文件:

    /// <summary>
    /// Create zip archive from root directory with search patterns
    /// </summary>
    /// <param name="rootDirectory">Root directory</param>
    /// <param name="searchPatterns">Search patterns</param>
    /// <param name="zipFileName">Zip archive file name</param>
    public static void CreateZip(string rootDirectory, List<string> searchPatterns, string zipFileName)
    {
        var fileNames = GetFileNames(rootDirectory, searchPatterns, true);
        CreateZipFromFileNames(rootDirectory, zipFileName, fileNames);
    }
    /// <summary>
    /// Get file names filtered by search patterns
    /// </summary>
    /// <param name="rootDirectory">Root diirectory</param>
    /// <param name="searchPatterns">Search patterns</param>
    /// <param name="includeSubdirectories">True if it is included files from subdirectories</param>
    /// <returns>List of file names</returns>
    private static IEnumerable<string> GetFileNames(string rootDirectory, List<string> searchPatterns, bool includeSubdirectories)
    {
        var foundFiles = new List<string>();
        var directoriesToSearch = new Queue<string>();
        directoriesToSearch.Enqueue(rootDirectory);
        // Breadth-First Search
        while (directoriesToSearch.Count > 0)
        {
            var path = directoriesToSearch.Dequeue();
            foreach (var searchPattern in searchPatterns)
            {
                foundFiles.AddRange(Directory.EnumerateFiles(path, searchPattern));
            }
            if (includeSubdirectories)
            {
                foreach (var subDirectory in Directory.EnumerateDirectories(path))
                {
                    directoriesToSearch.Enqueue(subDirectory);
                }
            }
        }
        return foundFiles;
    }
    /// <summary>
    /// Create zip archive from list of file names
    /// </summary>
    /// <param name="rootDirectroy">Root directory (for saving required structure of directories)</param>
    /// <param name="zipFileName">File name of zip archive</param>
    /// <param name="fileNames">List of file names</param>
    private static void CreateZipFromFileNames(string rootDirectroy, string zipFileName, IEnumerable<string> fileNames)
    {
        var rootZipPath = Directory.GetParent(rootDirectroy).FullName;
        using (var zip = new ZipFile(zipFileName))
        {
            foreach (var filePath in fileNames)
            {
                var directoryPathInArchive = Path.GetFullPath(Path.GetDirectoryName(filePath)).Substring(rootZipPath.Length);
                zip.AddFile(filePath, directoryPathInArchive);
            }
            zip.Save();
        }
    }

使用示例:

CreateZip("dir", new List<string> { "*.exe", "*.bat" }, "myFiles.zip");

@Didgeridoo说:DotNetZip。但是DotNetZip可以让您更具表现力。例如:

string cwd = Environment.CurrentDirectory ;
try
{
  Environment.CurrentDirectory = @"c:'root'of'directory'tree'to'be'zipped" ;
  using ( ZipFile zipfile = new ZipFile() )
  {
    zipfile.AddSelectedFiles( "name = *.bat OR name = *.exe" , true ) ;
    zipfile.Save( @"c:'foo'bar'my-archive.zip") ;
  }
}
finally
{
  Environment.CurrentDirectory = cwd ;
}

编辑注: DotNetZip曾经生活在Codeplex。Codeplex已关闭。旧的存档文件在Codeplex上仍然可用。看起来代码已经迁移到Github:

  • https://github.com/DinoChiesa/DotNetZip。看起来是原作者的repo。
  • https://github.com/haf/DotNetZip.Semverd。这看起来是当前维护的版本。它也可以通过Nuget在https://www.nuget.org/packages/DotNetZip/
  • 获得。