如何创建 zip 存档仅包含具有特定扩展名的文件
How to create zip archive contains files with certain extensions only
我需要创建 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
我知道如何通过 Directory.GetFiles 方法找到这些文件:
var ext = new List<string> {".exe", ".bat"};
var myFiles = Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories)
.Where(s => ext.Any(e => s.EndsWith(e));
但那时我不知道如何保存存档的结构。
我怎样才能实现这种行为?
您可以从所有子目录中获取扩展名为 .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 和文件夹 structure.You 可以找到文件信息详细信息 Here
System.IO.Directory.GetFiles("C:\temp", "*.exe", SearchOption.AllDirectories);
将 return 一个包含完整文件路径的数组,例如:
[C:\temp\dir1\app1.exe]
[C:\temp\dir2\subdir1\app2.exe]
[C:\temp\dir3\subdir2\subdir3\app3.exe]
因此,将这些文件放入带有 ZipArchive.CreateEntry 的 zip 容器中不会有任何问题,因为此方法将在 zip 中创建相同的目录结构。但是,您应该删除开头的 C:\
。
我相信这个非常好 tutorial 会帮助你做到这一点。
如果你想在目标 zip 中保留空文件夹,也许你必须使用 ZipArchive.CreateEntry
方法来做。在这个demo中,作者只使用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. But 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 已关闭。旧存档仍然是 available at Codeplex。看起来代码已经迁移到 Github:
- https://github.com/DinoChiesa/DotNetZip。看起来是原作者的回购。
- https://github.com/haf/DotNetZip.Semverd. This looks to be the currently maintained version. It's also packaged up an available via Nuget at https://www.nuget.org/packages/DotNetZip/
我需要创建 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
我知道如何通过 Directory.GetFiles 方法找到这些文件:
var ext = new List<string> {".exe", ".bat"};
var myFiles = Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories)
.Where(s => ext.Any(e => s.EndsWith(e));
但那时我不知道如何保存存档的结构。
我怎样才能实现这种行为?
您可以从所有子目录中获取扩展名为 .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 和文件夹 structure.You 可以找到文件信息详细信息 Here
System.IO.Directory.GetFiles("C:\temp", "*.exe", SearchOption.AllDirectories);
将 return 一个包含完整文件路径的数组,例如:
[C:\temp\dir1\app1.exe]
[C:\temp\dir2\subdir1\app2.exe]
[C:\temp\dir3\subdir2\subdir3\app3.exe]
因此,将这些文件放入带有 ZipArchive.CreateEntry 的 zip 容器中不会有任何问题,因为此方法将在 zip 中创建相同的目录结构。但是,您应该删除开头的 C:\
。
我相信这个非常好 tutorial 会帮助你做到这一点。
如果你想在目标 zip 中保留空文件夹,也许你必须使用 ZipArchive.CreateEntry
方法来做。在这个demo中,作者只使用ZipArchive. CreateEntryFromFile
方法从一个文件路径归档一个文件。
您也可以使用 DotNetZip 库来解决您的问题。例如,以下代码片段可以帮助您。使用 CreateZip()
方法。简而言之,您应该找到用于写入存档 GetFileNames()
的文件并使用 CreateZipFromFileNames()
:
/// <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. But 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 已关闭。旧存档仍然是 available at Codeplex。看起来代码已经迁移到 Github:
- https://github.com/DinoChiesa/DotNetZip。看起来是原作者的回购。
- https://github.com/haf/DotNetZip.Semverd. This looks to be the currently maintained version. It's also packaged up an available via Nuget at https://www.nuget.org/packages/DotNetZip/