C#创建包含多个文件的ZipArchive

C#创建包含多个文件的ZipArchive,c#,zip,C#,Zip,我的方法获取一个列表并创建一个ZIP文件和一个日志文件。它可以处理较小数量的文件。但当我处理大量文件(用11000测试)时,它抛出一个SystemOutOfMemory异常 通过研究,我了解到我的方法可能会给记忆带来很大的负担。所以我加入了我刷新streamwriter和zip存档的部分。我可能需要对文件流做些什么 解决这个问题的有效方法是什么 代码如下: public static void BackupFilesToZip(string directory, string f

我的方法获取一个列表并创建一个ZIP文件和一个日志文件。它可以处理较小数量的文件。但当我处理大量文件(用11000测试)时,它抛出一个SystemOutOfMemory异常

通过研究,我了解到我的方法可能会给记忆带来很大的负担。所以我加入了我刷新streamwriter和zip存档的部分。我可能需要对文件流做些什么

解决这个问题的有效方法是什么

代码如下:

        public static void BackupFilesToZip(string directory, string fileFilter, string zipFilePath, bool backupInSubDir, string logFilePath, List<FileInfo> filesToBackup)
    {
        FileInfo logFile = new FileInfo(logFilePath);
        FileInfo zipFile = new FileInfo(zipFilePath);
        int numberOfFiles = filesToBackup.Count;

        if (!Directory.Exists(zipFile.DirectoryName)) Directory.CreateDirectory(zipFile.DirectoryName);

        using (FileStream zipToOpen = new FileStream(zipFile.FullName, FileMode.OpenOrCreate))
        {
            using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
            {
                ZipArchiveEntry readmeEntry = archive.CreateEntry(logFile.Name);
                using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                {
                    writer.WriteLine("This ZIP archive was created: " + DateTime.Now.ToString("MM/dd/yy HH:mm:ss"));
                    writer.WriteLine("ZIP File: " + zipFilePath);
                    writer.WriteLine("Source Directory: " + directory);
                    string backupInSubText = "yes";
                    if (!backupInSubDir) backupInSubText = "no";
                    writer.WriteLine("Subdirectories included: " + backupInSubText);
                    writer.WriteLine("Filter Critera: " + fileFilter);
                    writer.WriteLine("Number of Files selected: " + numberOfFiles + " (for # of files archived/skipped scroll down)");
                    writer.WriteLine("");
                    writer.WriteLine("File Log:");

                    int filesArchivedCounter = 0;
                    int filesSkippedCounter = 0;
                    int filesSum = 0;

                    TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.Normal);

                    foreach (FileInfo file in filesToBackup)
                    {
                        //ZipArchiveEntry readmeEntry = archive.CreateEntry(logFile.Name);
                        string DateTimeStampBegin = DateTime.Now.ToString("MM/dd/yy HH:mm:ss");

                        try
                        {
                            string relativePath = MakeRelativePath(directory, file.FullName);
                            archive.CreateEntryFromFile(file.FullName, relativePath);
                            writer.WriteLine(DateTimeStampBegin + " - " + DateTime.Now.ToString("HH:mm:ss") + " archived: " + file.FullName);
                            filesArchivedCounter++;
                        }
                        catch
                        {
                            writer.WriteLine(DateTimeStampBegin + " - " + " SKIPPED: " + file.FullName);
                            filesSkippedCounter++;
                        }

                        filesSum = filesSkippedCounter + filesArchivedCounter;
                        TaskbarManager.Instance.SetProgressValue(filesSum, numberOfFiles);

                        //write from memory to files every 75 items (to avoid out of memory exception)
                        if (filesSum % 75 == 0)
                        {
                            writer.Flush();
                            zipToOpen.Flush();
                        }
                    }

                    writer.WriteLine("");
                    writer.WriteLine("# of Files archived: " + filesArchivedCounter);
                    writer.WriteLine("# of Files skipped: " + filesSkippedCounter);
                }

                if (!String.IsNullOrEmpty(logFile.Name))
                {
                    if (!Directory.Exists(logFile.DirectoryName)) Directory.CreateDirectory(logFile.DirectoryName);
                    readmeEntry.ExtractToFile(logFile.FullName, true);
                }

                TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress); 
            }
        }
    }
public static void BackupFilesToZip(字符串目录、字符串文件过滤器、字符串zipFilePath、bool backupInSubDir、字符串日志文件路径、列表文件备份)
{
FileInfo logFile=newfileinfo(logFilePath);
FileInfo-zipFile=新文件信息(zipFilePath);
int numberOfFiles=filesToBackup.Count;
如果(!Directory.Exists(zipFile.DirectoryName))Directory.CreateDirectory(zipFile.DirectoryName);
使用(FileStream zipToOpen=newfilestream(zipFile.FullName,FileMode.OpenOrCreate))
{
使用(ZipArchive archive=new ZipArchive(zipToOpen,ZipArchiveMode.Update))
{
ZipArchiveEntry readmeEntry=archive.CreateEntry(logFile.Name);
使用(StreamWriter=newstreamwriter(readmeEntry.Open()))
{
WriteLine(“创建此ZIP存档:”+DateTime.Now.ToString(“MM/dd/yy HH:MM:ss”);
writer.WriteLine(“ZIP文件:+zipFilePath”);
writer.WriteLine(“源目录:+目录”);
字符串backupInSubText=“是”;
如果(!backupInSubDir)backupInSubText=“否”;
WriteLine(“包含子目录:“+backupInSubText”);
writer.WriteLine(“过滤器标准:+fileFilter”);
WriteLine(“所选文件数:+numberOfFiles+”(用于#已存档/跳过的文件向下滚动)”;
writer.WriteLine(“”);
WriteLine(“文件日志:”);
int filesArchivedCounter=0;
int fileskippedcounter=0;
int filesSum=0;
TaskbarManager.Instance.SetProgressState(taskbarProgressState.Normal);
foreach(filesToBackup中的FileInfo文件)
{
//ZipArchiveEntry readmeEntry=archive.CreateEntry(logFile.Name);
字符串DateTimeStampBegin=DateTime.Now.ToString(“MM/dd/yy HH:MM:ss”);
尝试
{
string relativePath=MakeRelativePath(目录,file.FullName);
archive.CreateEntryFromFile(file.FullName,relativePath);
WriteLine(DateTimeStampBegin+“-”+DateTime.Now.ToString(“HH:mm:ss”)+“存档:”+file.FullName);
FileArchivedCounter++;
}
抓住
{
writer.WriteLine(DateTimeStampBegin+“-”+”跳过:“+file.FullName);
FileSkippedCounter++;
}
filesSum=fileskippedcounter+filearchivedcounter;
TaskbarManager.Instance.SetProgressValue(filesSum,numberOfFiles);
//每75项从内存写入文件(以避免内存不足异常)
如果(文件总数%75==0)
{
writer.Flush();
zipToOpen.Flush();
}
}
writer.WriteLine(“”);
writer.WriteLine(“#已归档文件:“+filearchiveCounter”);
writer.WriteLine(“#跳过的文件数:“+fileskippedcounter”);
}
如果(!String.IsNullOrEmpty(logFile.Name))
{
如果(!Directory.Exists(logFile.DirectoryName))Directory.CreateDirectory(logFile.DirectoryName);
readmeEntry.ExtractToFile(logFile.FullName,true);
}
TaskbarManager.Instance.SetProgressState(taskbarProgressState.NoProgress);
}
}
}

此方法的所有字符串参数仅适用于日志文件。

实现中的问题是,您将日志条目放在归档文件的开头,并在添加新文件后进行更新,因此无法刷新zip。您应该将日志写入文件,而不是归档文件,并在添加所有文件时将其添加到归档文件。

也许可以从(MemoryMappedFile)而不是FileStream开始。我通读了所有MemoryMappedFile示例,并尝试实现它。但我无法让它工作。任何人都可以提供一个关于如何在此上下文中使用MemoryMappedFile(ZipArchive)的代码示例吗?