C # creates ZipArchive with many files

My method takes a list and creates a zip file and a log file. It works with fewer files. But when I go after a lot of files (checked with 11,000) it throws a SystemOutOfMemory exception.

From my research, I found out that my method is probably using most of the memory. So I included this part to clear the streamblock and zip archive. I probably should do something for the file stream.

What is an effective approach to solving this problem?

Here is the code:

        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); 
            }
        }
    }

      

All string parameters to this method are for the log file only.

+3


source to share


1 answer


The problem in your implementation is that you put an entry at the beginning of the archive and update it after adding new files, so the zip cannot be flushed. You should write the log to a file, not an archive, and add it to the archive when all files are added.



0


source







All Articles