2017-02-10 35 views
1

我正在用C#构建一个不错的软件。目标版本:.net 4.5。核心工作之一是构建一个文件列表(包含在根文件夹中的各个目录和子目录中),然后一次压缩一个文件。.net 4.5 ZipArchive - 我的软件或库中有内存泄漏吗?

我正在使用ZipArchive类包含在里面System.IO.Compression;

下面的代码:

// STEP 1 

      using (var fs = new FileStream(destination_path + "\\" + zipname + ".zip", FileMode.OpenOrCreate)) 
      { 

       using (var zip = new ZipArchive(fs, ZipArchiveMode.Update)) 
       {     

        // Some non important thing 

        foreach (string single_file in list_file_tobackup) 
        { 
         // non important things 

         zip.CreateEntryFromFile(single_file, temp); 

        } 
       } 

      }  
// STEP 2 

这是我身边已经发现了那么一点点的代码。 (可能)说这段代码包含在一个包含在静态类中的方法中,并从WPF窗口中调用是很重要的。在这个代码中使用的所有列表都是静态类本身声明的静态私有列表,所以它们将保留在内存中。

有什么问题?

当软件开始时(步骤1),它对RAM的内存影响很小(就像所有普通的小软件一样)。在所有文件被压缩后,最终到达结尾(步骤2),软件已经采用了大量内存并且永远不释放它。

如果我尝试压缩一个非常大的文件夹(大约400 MB),软件将在RAM上保留(即使方法完成时)将近1GB!如果我尝试更大的文件夹,它会简单地崩溃(System.OutOfMemoryException)。

只有当我用小文件夹再次运行该方法时,该软件才能释放内存。

起初我以为内存泄漏是由内存中保存的大量文件引起的。然后我使用了Visual Studio内存测试工具,并且我发现所有这些大内存都属于ZipArchive类,所以我无法进行更深入的调试。

我做错了什么或只是ZipAchive库不够好,我不得不做什么?

如果这是最后一个:存在一些更好的.zip库免费使用,没有太多的许可证约束?

+1

Zip更新方法将保留可能导致内存泄漏的旧文件和新文件。 – jdweng

回答

0

From MSDN 当您将模式设置为更新时,底层文件或流必须支持读取,写入和查找。整个存档的内容保存在内存中,并且在存档被丢弃之前不会将数据写入底层文件或流。

您是否尝试过使用ZipArchiveMode.Create?

如果您需要对现有存档执行更新,仍可以通过复制现有存档并创建新条目来使用创建。

+0

使用ZipArchiveMode.Create正在工作!所有文件都添加没有问题。 不幸的是,现在的软件已经完全坏了:我的问题中的代码片段在foreach循环中,所以第二次运行时它会覆盖之前的zip文件... 我没有理解最后一个短语,你能解释一下吗?我怎样才能做更多的ZipArchiveMode.Create实例来更新压缩文件,最后只有一个.zip文件和我的所有内容?我认为这是不可能的... –

+0

根据您的使用情况,每次创建一个新的存档并简单地覆盖以前是一个选项,也是最简单的选项。如果您试图压缩包含大量文件的非常大的目录,我会尝试创建第二个压缩文件(基本上是一个副本),并尝试复制压缩文件(如果文件未更改并添加新文件)。但是,这需要您执行差异等。 – Blackfield