• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1004
  • Last Modified:

Compress Directory + SubFolders using ZipOutputStream

Hi.  I'm trying to compress a folder (and it's subdirectories).  I've adapted code I've found on the net which zip's up the files within the folder specified, but not the sub-folders (ie, the entire contents).

Here's the code:
---------
string[] filenames = Directory.GetFiles(str_vledatasource.Text);
using (ZipOutputStream s = new ZipOutputStream(File.Create(str_vledatadestination.Text+"\\VLE Backup ("+ strTimeStamp.ToString()+").zip")))
                {

                    s.SetLevel(9); // 0-9, 9 being the highest compression
                    byte[] buffer = new byte[4096];

                    foreach (string file in filenames)
                    {
                        ZipEntry entry = new
                        ZipEntry(Path.GetFileName(file));
                        entry.DateTime = DateTime.Now;
                        s.PutNextEntry(entry);
                        using (FileStream fs = File.OpenRead(file))

                      {

                            int sourceBytes;
                            do
                            {

                               sourceBytes = fs.Read(buffer, 0, buffer.Length);
                               s.Write(buffer, 0, sourceBytes);
                            }

                            while (sourceBytes > 0);
                        }

                    }

                    s.Finish();
                    s.Close();

--

Can anyone help me finish this off, please?
str_vledatasource.Text is the string for the location
str_vledatadestination.Text is the string for the output/destination of the zip.
Thanks.


0
nikez2k4
Asked:
nikez2k4
  • 6
  • 6
1 Solution
 
SimonFerrisCommented:
You'll need to recurse the directory structure for all sub directories. See http://support.microsoft.com/default.aspx/kb/303974/ for information on recursion,

The section below is the part where you recurse and I've commented the part where you would do the compression.

void DirSearch(string sDir)
{
      try      
      {
         foreach (string d in Directory.GetDirectories(sDir))
         {
            foreach (string f in Directory.GetFiles(d, txtFile.Text))
            {
               // .. do the compression here
            }
            DirSearch(d);
         }
      }
      catch (System.Exception excpt)
      {
            Console.WriteLine(excpt.Message);
      }
}
0
 
nikez2k4Author Commented:
Thx. Have put that together:
.......
 {

             try      
      {
         foreach (string d in Directory.GetDirectories(sDir))
         {
            foreach (string f in Directory.GetFiles(d, txtFile.Text))
            {
            // --
            string strTimeStamp = "test";
            string[] filenames = Directory.GetFiles(str_vledatasource.Text);
            using (ZipOutputStream s = new ZipOutputStream(File.Create(str_vledatadestination.Text + "\\VLE Backup (" + strTimeStamp + ").zip")))
            {

                s.SetLevel(9); // 0-9, 9 being the highest compression
                byte[] buffer = new byte[4096];

                foreach (string file in filenames)
                {
                    ZipEntry entry = new
                    ZipEntry(Path.GetFileName(file));
                    entry.DateTime = DateTime.Now;
                    s.PutNextEntry(entry);
                    using (FileStream fs = File.OpenRead(file))
                    {

                        int sourceBytes;
                        do
                        {

                            sourceBytes = fs.Read(buffer, 0, buffer.Length);
                            s.Write(buffer, 0, sourceBytes);
                        }


                        while (sourceBytes > 0);

                    }

                }

                s.Finish();

                s.Close();

            }

        }
        DirSearch(d);
    }
}
catch (System.Exception excpt)
{
    Console.WriteLine(excpt.Message);
}
        }

.............

But I'm getting:

Error      1      The name 'sDir' does not exist in the current context
Error      2      The name 'txtFile' does not exist in the current context
Error      3      The name 'DirSearch' does not exist in the current context

Have I got this back to front? Or....
0
 
SimonFerrisCommented:
From the example txtFile is a filter as is defined higher up in the code sample as a text box, sDir should be visible as it is not out of scope at this point (is the casing correct sDir rather than sdir?). Change void DirSearch to public void DirSearch - this may solve the issue but I haven't the time to write out a test app. :)
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
nikez2k4Author Commented:
Ah yes. Was being a bit blind there. Have sorted that. Just down now to my lack of experience I think --
public void DirSearch(string sDir)  ... worked fine.

How can I call this now, on an eventhandler? When I try to call it I get:
Error      1      No overload for method 'DirSearch' takes '0' arguments

Hopefully the last hurdle. Thanks ;-)

0
 
SimonFerrisCommented:
Add something like
protected void btn_click(object sender, EventArgs e)
//This would be a button on the form that you want to start the process
{
    DirSearch(<insert search string here>)
}

Where <insert search string> replace with the string that you want to start the recursion from, this could be populated from a textbox or dropdown.
0
 
nikez2k4Author Commented:
So Close! :-P
Thanks for this.  I'm sure I'm doing something wrong, as I get:
"Second path fragment must not be a drive or unc name  Parameter Name: Path2" Error...
I was saving the file in "C:\"
Did a quick google and can't see anything that stands out.

            string[] filenames = Directory.GetFiles(str_vledatasource.Text);   // <--- The location of the files
            foreach (string file in filenames)

Looks the same as this: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=206202&SiteID=1
Any ideas? Will chuck in some more points, sorry - it wasn't as straight forward as I thought at first! ;-)
0
 
SimonFerrisCommented:
About to go home now. I'll have a run through the code later and post any ideas.
0
 
SimonFerrisCommented:
If you use  foreach (string d in Directory.GetDirectories(sDir,"*",SearchOption.AllDirectories)) it will recurse all subdirectories. It will raise an exception if you specify C: as there are protected directories.

I ran the example I gave and it didn't throw an error. It looks as though it is in the string[] GetFiles() part - could it be that there is a limit to the array that is getting filled.
0
 
nikez2k4Author Commented:
Strange. I tried it on a folder (removable HDD) F:\Photos (which has 4 folders of pictures in) - and the output path to be C:\ <then the filename from the destination string>.zip.
I added in your last comment about SearchOption, but it didnt change it:
-
        public void DirSearch(string sDir) {

             try      
      {
          foreach (string d in Directory.GetDirectories(sDir, "*", SearchOption.AllDirectories))
         {
            foreach (string f in Directory.GetFiles(d, str_vledatasource.Text))
            {
            // --
            string strTimeStamp = "dave";
            string[] filenames = Directory.GetFiles(str_vledatasource.Text);
            using (ZipOutputStream s = new ZipOutputStream(File.Create(str_vledatadestination.Text + "\\VLE Backup (" + strTimeStamp + ").zip")))
            {

.....

-
0
 
SimonFerrisCommented:
It looks as though it may be foreach (string f in Directory.GetFiles(d, str_vledatasource.Text))  that is causing the error as the overloaded method Directory.GetFiles(string a, string b) a=drive location and b=filter and in your code b=directory.
0
 
nikez2k4Author Commented:
Hmm, okay. Is there another way around this?
I found this, which loosk to be a possible solution but no idea where to start hackin' and slashin' to make it all fit...
http://community.sharpdevelop.net/forums/thread/16977.aspx 
0
 
nikez2k4Author Commented:
Sorted it... Here's the final solution for anyone else interested (You'll need to note the variables/textboxes):
-
    public  void CompressDirectory(string path, int compressionlevel)
        {
           
           
            string strTimeStamp = "dave";
            string zipfilename = path.TrimEnd('\\', '/') + ".zip";
            using (ZipOutputStream zip = new ZipOutputStream(File.Create(str_vledatadestination.Text + "\\VLE Backup (" + strTimeStamp + ").zip")))
            {
                zip.SetLevel(compressionlevel);
                string rootpath = path.Substring(0, path.LastIndexOfAny("\\/".ToCharArray()) + 1);
                foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
                    WriteToZip(file, file.Replace(rootpath, null), zip);

                zip.Finish();
            }
        }

        public  void WriteToZip(string file, string entrypath, ZipOutputStream zip)
        {
            ZipEntry entry = new ZipEntry(entrypath);
            entry.DateTime = DateTime.Now;
            zip.PutNextEntry(entry);
            if (!string.IsNullOrEmpty(file))
            {
                using (FileStream fs = File.OpenRead(file))
                {
                    byte[] buffer = new byte[4096];
                    int bytes = 1;
                    while (bytes > 0)
                    {
                        bytes = fs.Read(buffer, 0, buffer.Length);
                        zip.Write(buffer, 0, bytes);
                    }
                }
            }
        }

   
--

Points to Simon for his guidance 'cos I couldnt have done it without his help.  Thanks Simon!
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

  • 6
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now