2016-02-15 99 views
3

我試圖創建一個zip文件作爲目錄的備份,並最終將該備份保存在該目錄中的「備份」文件夾中。爲了說明,「文件夾」包括「subFolder」,「file1.txt」,「file2.txt」和「備份」。 「備份」文件夾將包含各種早期的備份文件。我想創建「文件夾」及其所有內容(包括子文件夾)的存檔,但不包括「備份」。如何壓縮除一個子目錄以外的目錄內容?

這是我原想用:

ZipFile.CreateFromDirectory(folderToZip, backupFileName); 

我知道有拯救被壓縮的文件夾內的一個zip文件的問題,所以我打算到別處保存,然後將其傳送。但我不知道如何輕鬆創建沒有備份文件夾的存檔。我唯一的想法是寫我自己的方法遞歸遍歷目錄,並排除該文件夾。似乎必須有一個更簡單的方法。

任何幫助將不勝感激!

回答

6

不幸的是,ZipFile沒有提供讓您過濾條目的方法。幸運的是,你可以輕鬆地創建基於this implementation這樣的方法:

public static class ZipHelper { 
    public static void CreateFromDirectory(
     string sourceDirectoryName 
    , string destinationArchiveFileName 
    , CompressionLevel compressionLevel 
    , bool includeBaseDirectory 
    , Encoding entryNameEncoding 
    , Predicate<string> filter // Add this parameter 
    ) { 
     if (string.IsNullOrEmpty(sourceDirectoryName)) { 
      throw new ArgumentNullException("sourceDirectoryName"); 
     } 
     if (string.IsNullOrEmpty(destinationArchiveFileName)) { 
      throw new ArgumentNullException("destinationArchiveFileName"); 
     } 
     var filesToAdd = Directory.GetFiles(sourceDirectoryName, "*", SearchOption.AllDirectories); 
     var entryNames = GetEntryNames(filesToAdd, sourceDirectoryName, includeBaseDirectory); 
     using(var zipFileStream = new FileStream(destinationArchiveFileName, FileMode.Create)) { 
      using (var archive = new ZipArchive(zipFileStream, ZipArchiveMode.Create)) { 
       for (int i = 0; i < filesToAdd.Length; i++) { 
        // Add the following condition to do filtering: 
        if (!filter(filesToAdd[i])) { 
         continue; 
        } 
        archive.CreateEntryFromFile(filesToAdd[i], entryNames[i], compressionLevel); 
       } 
      } 
     } 
    } 
} 

這一實現使您通過一個過濾器,拒絕來自"backup/"目錄中的所有條目:

ZipHelper.CreateFromDirectory(
    myDir, destFile, CompressionLevel.Fastest, true, Encoding.UTF8, 
    fileName => !fileName.Contains(@"\backup\") 
); 
+0

我會用'Directory.EnumerateFiles'和'foreach'循環,除非我確保永遠不會有包含大量文件的目錄。 – Haukinger

+0

@Haukinger我也會這樣做,但我決定繼續實施,以接近原始,以說明爲了實現OP的要求,需要改變的很少。 – dasblinkenlight

+0

謝謝你的幫助!我很感激! – randomraccoon

1

在我看來,你可以將文件夾內的每個文件都排除在「備份」文件夾之外,並使用它們創建一個臨時文件夾以製作壓縮文件,如您所說。

有了這個LINQ查詢,你可以做一個非常簡單的方法:

List<FileInfo> files = di.GetFiles("*", SearchOption.AllDirectories).Where(file => !file.DirectoryName.Contains("backups")).ToList(); 

一旦你有了這個列表,您可以複製所有這些文件,使拉鍊和擦除的內容。我看不到一個更簡單的方法。

0

可以擴展添加到ZipArchive:

public static void ZipDirectory(this ZipArchive zipArchive, string srcDir, IEnumerable<Regex> excludeFileList = null, IEnumerable<Regex> excludeDirList = null , string rootDir = "") 
    { 
     if (!Directory.Exists(srcDir)) throw new Exception("source directory for zipping doesn't exit"); 
     var dir = new DirectoryInfo(srcDir); 

     dir.GetFiles().ToList().ForEach((file) => { 
      if (excludeFileList == null || excludeFileList.Where(rule => rule.IsMatch(file.Name)).Count() == 0) 
      { 
       zipArchive.CreateEntryFromFile(file.FullName, string.IsNullOrEmpty(rootDir) ? file.Name : [email protected]"{rootDir}\{file.Name}"); 
      }}); 

     dir.GetDirectories().ToList().ForEach((directory) => { 
      if (excludeDirList == null || excludeDirList.Where(rule => rule.IsMatch(directory.Name)).Count() == 0) 
      { 
       zipArchive.ZipDirectory(directory.FullName, excludeFileList, excludeDirList, string.IsNullOrEmpty(rootDir) ? [email protected]"{directory.Name}" : [email protected]"{rootDir}\{directory.Name}"); 
      }}); 
    } 

,並使用它像:

var excludeFileList = new List<Regex>() { new Regex(".pdb$") }; 

using (var zipFileStream = new FileStream(zipFile, FileMode.Create)) 
{ 
    using (var zipArch = new ZipArchive(zipFileStream, ZipArchiveMode.Create)) 
    { 
      zipArch.ZipDirectory(src, excludeFileList); 
    } 
} 
相關問題