Monday, February 18, 2008

Zipping files for Windows Explorer

As part of my automated build process, I wanted to be able to ZIP up files. For this I used the excellent (and free!) ZipLib, but there a few gotchas if you want your generated ZIP files to be readable by the built-in Windows compressed folders functionality.

First, Windows XP doesn't like the Zip64 format used by default so that needs to turned off. Second, Windows doesn't like the full path to be included in the file names inside your ZIP file. This means the easiest to use ZipFile class can't be used. Finally, if you're planning to ZIP up the contents of a directory, make sure you delete any ZIP file that was created previously, otherwise you'll try and ZIP up the already created ZIP file.

All of these caught me out, but this is what I came up with that now seems to work.

      string fileName = Path.Combine(zipFolder, zipFileName);

      // delete the ZIP file if it exists already
      if (File.Exists(fileName))
        File.Delete(fileName);

      DirectoryInfo info = new DirectoryInfo(zipFolder);
      FileInfo[] files = info.GetFiles();

      // zip up the required files
      using (ZipOutputStream zipOutputStream = new ZipOutputStream(File.Create(fileName)))
      {
        zipOutputStream.UseZip64 = UseZip64.Off;
        byte[] buffer = new byte[4096];
        for (int i = 0; i < files.Length; i++)
        {
          ZipEntry entry = new ZipEntry(files[i].Name);

          entry.DateTime = DateTime.Now;
          zipOutputStream.PutNextEntry(entry);

          using (FileStream fs = File.OpenRead(files[i].FullName))
          {
            entry.Size = fs.Length;

            int sourceBytes;
            do
            {
              sourceBytes = fs.Read(buffer, 0, buffer.Length);
              zipOutputStream.Write(buffer, 0, sourceBytes);
            }
            while (sourceBytes > 0);
          }
        }

        zipOutputStream.Finish();
        zipOutputStream.Close();
      }

No comments: