Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DotNetZip - Calculate final zip size before calling Save(stream) in C#

Tags:

c#

dotnetzip

When using DotNetZip, is it possible to get what the final zip file size will be before calling Save(stream)? I have a application(Window Service) where package Stream size is more than 100MB then package will saved and upcoming files add into new package.

I got same question for web application but not understand the answer. Is there any way into DotnetZip to find the size of zip stream before save on I/O system?

like image 298
Saroop Trivedi Avatar asked May 30 '12 11:05

Saroop Trivedi


2 Answers

I got the solution. Here is code.Now I will create the package which size is less then 100MB.

using System;
using System.Collections;
using System.IO;
using Ionic.Zip;
using Ionic.Zlib;

namespace ZipFileSize1
{
    /// <summary>
    /// This source code is generate the specified size Packages from the directory.
    /// </summary>
    class Program
    {
        /// <summary>
        /// The size of Package(100MB).
        /// </summary>
        public static long m_packageSize = 1024 * 1024 * 100;

        /// <summary>
        ///  Main method of program class.
        /// </summary>
        /// <param name="args">Command line argument</param>
        static void Main(string[] args)
        {
            Console.WriteLine("Enter Directory Full Name for Compression : ");
            var dir = Console.ReadLine();
            Console.WriteLine("Zip File saved Location Directory Name : ");
            var savedir = Console.ReadLine();

            //generate the random zip files.

            var zipFile = Path.Combine(savedir, DateTime.Now.Ticks + ".zip");
            ZipFiles(dir, savedir);

            Console.ReadLine();
        }

        /// <summary>
        /// This method generate the package as per the <c>PackageSize</c> declare.
        /// Currently <c>PackageSize</c> is 100MB.
        /// </summary>
        /// <param name="inputFolderPath">Input folder Path.</param>
        /// <param name="outputFolderandFile">Output folder Path.</param>
        public static void ZipFiles(string inputFolderPath, string outputFolderandFile)
        {
            ArrayList ar = GenerateFileList(inputFolderPath); // generate file list
            int trimLength = (Directory.GetParent(inputFolderPath)).ToString().Length;
            // find number of chars to remove   // from original file path
            trimLength += 1; //remove '\'

            // Output file stream of package.
            FileStream ostream;
            byte[] obuffer;

            // Output Zip file name.
            string outPath = Path.Combine(outputFolderandFile, DateTime.Now.Ticks + ".zip");

            ZipOutputStream oZipStream = new ZipOutputStream(File.Create(outPath), true); // create zip stream

            // Compression level of zip file.
            oZipStream.CompressionLevel = CompressionLevel.Default;

            // Initialize the zip entry object.
            ZipEntry oZipEntry = new ZipEntry();

            // numbers of files in file list.
            var counter = ar.Count;
            try
            {
                using (ZipFile zip = new ZipFile())
                {
                    Array.Sort(ar.ToArray());  // Sort the file list array.
                    foreach (string Fil in ar.ToArray()) // for each file, generate a zip entry
                    {
                        if (!Fil.EndsWith(@"/")) // if a file ends with '/' its a directory
                        {

                            if (!zip.ContainsEntry(Path.GetFullPath(Fil.ToString())))
                            {
                                oZipEntry = zip.AddEntry(Path.GetFullPath(Fil.ToString()), Fil.Remove(0, trimLength));
                                counter--;
                                try
                                {
                                    if (counter > 0)
                                    {
                                        if (oZipStream.Position < m_packageSize)
                                        {
                                            oZipStream.PutNextEntry(oZipEntry.FileName);
                                            ostream = File.OpenRead(Fil);
                                            obuffer = new byte[ostream.Length];
                                            ostream.Read(obuffer, 0, obuffer.Length);
                                            oZipStream.Write(obuffer, 0, obuffer.Length);
                                        }

                                        if (oZipStream.Position > m_packageSize)
                                        {
                                            zip.RemoveEntry(oZipEntry);
                                            oZipStream.Flush();
                                            oZipStream.Close(); // close the zip stream.
                                            outPath = Path.Combine(outputFolderandFile, DateTime.Now.Ticks + ".zip"); // create new output zip file when package size.
                                            oZipStream = new ZipOutputStream(File.Create(outPath), true); // create zip stream                                                
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("No more file existed in directory");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.Message);
                                    zip.RemoveEntry(oZipEntry.FileName);
                                }

                            }
                            else
                            {
                                Console.WriteLine("File Existed {0} in Zip {1}", Path.GetFullPath(Fil.ToString()), outPath);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);

            }
            finally
            {
                oZipStream.Flush();
                oZipStream.Close();// close stream
                Console.WriteLine("Remain Files{0}", counter);
            }
        }

        /// <summary>
        /// This method return the list of files from the directory
        /// Also read the child directory also, but not add the 0 length file.
        /// </summary>
        /// <param name="Dir">Name of directory.</param>
        /// <returns>return the list of all files including into subdirectory files </returns>
        private static ArrayList GenerateFileList(string Dir)
        {
            ArrayList fils = new ArrayList();

            foreach (string file in Directory.GetFiles(Dir, "*.*", SearchOption.AllDirectories)) // add each file in directory
            {
                if (File.ReadAllBytes(file).Length > 0)
                    fils.Add(file);
            }

            return fils; // return file list
        }      
    }
}
like image 103
2 revs Avatar answered Sep 24 '22 04:09

2 revs


not understand the answer

The answer is quite clear, but requires some fundamental understanding of compression. Take, for example, a look at LZW.

It comes down to this: a compression engine does not know the final size of the compressed data before compressing all the source data. And you'd rather not want to do that twice.

As explained in the documentation of dotnetzip, the compression only starts when calling ZipFile.Save().

like image 23
CodeCaster Avatar answered Sep 21 '22 04:09

CodeCaster