-3

I've following function which creates a Zip file, it works good when the number of files are few thousands. However, this isn't a efficient solution in a time bound operation. I was wondering if an asynchronous concurrency can be added so that it will minimise the overall time taken to complete the operation.

Code:

public static void CreateZip()
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    string dirRoot = @"C:\Dir\";

    //get a list of files
    string[] filesToZip = Directory.GetFiles(dirRoot, "*.*",
        SearchOption.AllDirectories);

    string zipFileName = @"C:\Dir.zip";

    using (MemoryStream zipMS = new MemoryStream())
    {
        using (ZipArchive zipArchive = new ZipArchive(zipMS, ZipArchiveMode.Create,
            true))
        {

            //loop through files to add
            foreach (string fileToZip in filesToZip)
            {
                //read the file bytes
                byte[] fileToZipBytes = System.IO.File.ReadAllBytes(fileToZip);

                //create the entry - this is the zipped filename
                //change slashes - now it's VALID
                ZipArchiveEntry zipFileEntry = zipArchive.CreateEntry(
                    fileToZip.Replace(dirRoot, "").Replace('\\', '/'));

                //add the file contents
                using (Stream zipEntryStream = zipFileEntry.Open())
                using (BinaryWriter zipFileBinary = new BinaryWriter(zipEntryStream))
                {
                    zipFileBinary.Write(fileToZipBytes);
                }
            }
        }

        using (FileStream finalZipFileStream = new FileStream(zipFileName,
            FileMode.Create))
        {
            zipMS.Seek(0, SeekOrigin.Begin);
            zipMS.CopyTo(finalZipFileStream);
        }
        stopwatch.Stop();
        Console.WriteLine("Total time elapsed: {0}",
            stopwatch.ElapsedMilliseconds / 1000);
    }
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Aniruddha
  • 837
  • 3
  • 13
  • 37

1 Answers1

1

I see no mentioning that any methods on zipArchive are thread safe. Therefore it should be assumed they are not, and that you cannot call it from multiple threads without bad things happening.

You could run the whole method as a task on a background thread thus not blocking the main thread, see asynchronous programming and Task.Run. It is usually also nice to show a progress bar to the user. But this will not make the actual compression time any faster.

There are also other compression libraries, i know that 7zip support multi threaded compression, but there might be others.

Also, if you just want to create an archive from a directory, you might want to use CreateFromDirectory

You can select the compression level when creating entries to provide a trade off between speed and size. SharpZipLib might provide a bit more additional flexibility. But there are only so much this will do, compressing files involve a lot of IO operations, and this is fundamentally slow.

JonasH
  • 28,608
  • 2
  • 10
  • 23