-1

I am using dotnet zip library to create zip file. My files are saved into a database and I am reading each row and load file data into memory from the database and save the memory stream to zip file. my below code works fine.

using System.IO;
using Ionic.Zip;

private void button2_Click(object sender, EventArgs e)
        {
            using (SqlConnection sqlConn = new SqlConnection(@"Data Source=BBATRIDIP\SQLSERVER2008R2;Initial Catalog=test;Integrated Security=True"))
            {
                string query = String.Format(@"SELECT Name, ContentType, Data FROM [TestTable]");
                SqlCommand cmd = new SqlCommand(query, sqlConn);
                cmd.Connection.Open();

                System.IO.MemoryStream memStream = null;
                ZipFile zip = new ZipFile();
                zip.MaxOutputSegmentSize = 1024 * 1024; // 1MB each segment size would be
                // the above line would split zip file into multiple files and each file
                //size would be 1MB
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        byte[] data = (byte[])reader["Data"];
                        memStream = new System.IO.MemoryStream(data);
                        string strFile = reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
                        ZipEntry ze = zip.AddEntry(strFile, memStream);
                        int xx = 0;
                    }
                }
                zip.Save(@"e:\MyCustomZip.zip");

                memStream.Dispose();
                MessageBox.Show("Job Done");
                // here u can save the zip in memory stream also there is a overload insteaa of saving in HD
            }
        }

but if i change a bit into the code then corrupted zip file is creating. if i change this line zip.Save(@"e:\MyCustomZip.zip"); then problem occur.

    using (SqlConnection sqlConn = new SqlConnection(@"Data Source=BBATRIDIP\SQLSERVER2008R2;Initial Catalog=test;Integrated Security=True"))
    {
        string query = String.Format(@"SELECT Name, ContentType, Data FROM [TestTable]");
        SqlCommand cmd = new SqlCommand(query, sqlConn);
        cmd.Connection.Open();

        System.IO.MemoryStream memStream = null;
        ZipFile zip = new ZipFile();
        zip.MaxOutputSegmentSize = 1024 * 1024; // 1MB each segment size would be
        // the above line would split zip file into multiple files and each file
        //size would be 1MB
        zip.Save(@"e:\MyCustomZip.zip");
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                byte[] data = (byte[])reader["Data"];
                memStream = new System.IO.MemoryStream(data);
                string strFile = reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
                ZipEntry ze = zip.AddEntry(strFile, memStream);
                int xx = 0;
            }
        }


        memStream.Dispose();
        MessageBox.Show("Job Done");
        // here u can save the zip in memory stream also there is a overload insteaa of saving in HD
    }

I want to create zip with zero kb initially and when I will add stream to zip in loop then zip file size will increase gradually. if you see my above code where I try to do that but I got no success. what am I doing wrong in the code?

Another issue

dotnet zip compression ratio not good. i zip a 152 KB doc file with dotnet zip and when zip was created then i was zip file size was 136KB. is there any tweak exist which create small size zip file. share the knowledge. thanks

Mou
  • 15,673
  • 43
  • 156
  • 275
  • It's wrong to save a file and then add stuff to it. It's the other way around. It is strange that the library would even allow this. Probably a bug. – usr Apr 22 '15 at 11:06
  • If the library allowed it your code work, wouldn't it? – usr Apr 22 '15 at 11:09
  • library allow but when run then a corrupted zip is creating. – Mou Apr 22 '15 at 11:11

1 Answers1

1

So, looking at the documentation for ZipFile.Save, we see the following:

Use this when creating a new zip file, or when updating a zip archive.

So, it seems that you need to call this repeatedly to get the "update" behaviour you are looking for. As such just need to move your Save into the loop:

//...
ZipFile zip = new ZipFile();
zip.MaxOutputSegmentSize = 1024 * 1024; 

using (SqlDataReader reader = cmd.ExecuteReader())
{
    while (reader.Read())
    {
        byte[] data = (byte[])reader["Data"];
        memStream = new System.IO.MemoryStream(data);
        string strFile = 
            reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
        ZipEntry ze = zip.AddEntry(strFile, memStream);
        zip.Save(@"e:\MyCustomZip.zip");
    }
}

With regards to your second question (never a good idea on SO, try to stick to one problem per question):

Without knowing what you are compressing, it's very difficult to speculate about what kind of compression ratio you might achieve. If the data is already compressed (e.g. compressed image/video such as jpeg/h264), zipping isn't going to give you any gains whatsoever. Your only hint about the nature of the content is that it is a "doc". If you're talking about a modern Word document (docx), this is already a zip compressed folder structure. Gains will be minimal. If it's another kind of doc, perhaps it contains embedded (compressed) media? This will also be relatively incompressible.

spender
  • 117,338
  • 33
  • 229
  • 351
  • i was trying to zip a doc file whose size was 152 KB and after creating zip file i was size become 136KB. not very good i guess. is there any option to tweak anything in code to get better compression. let me know. thanks – Mou Apr 22 '15 at 11:24
  • @Mou: What is a "doc"? A word document? Docx? – spender Apr 22 '15 at 11:26
  • The Save call is supposed to be made when all data has been added. Calling it in a loop might even exhibit quadratic time behavior. – usr Apr 22 '15 at 11:28
  • @usr Yes, I was considering this might be the case too. I suppose it's down to OP to test whether it gives acceptable performance. I'm struggling to understand the use-case for such code... – spender Apr 22 '15 at 11:32