tags:

views:

399

answers:

5

I wanted to use .net's System.IO.Compression.GZipStream to compress and decompress a directory. But I find it only able to compress a single file, how can I write a zip class that can compress a specific directory to a zip file?

ps: we're not allowed to use any third party zip library

+3  A: 

You should TAR the files first.

EDIT

If you are feeling adventurous why don't you design your own header and write each zipped file sequentially. Store all the file names in the header and the index of where they start.

ChaosPandion
in fact our team is using SharpZipLib but our team leader was worrying about the potential LCA issue, so we'd to write a simple class by ourselves. Besides, our compressed file should be compatible with the standard.
CMinus
I've tried Google but there is a lot of conflicting definitions for LCA. Also our team uses SharpZipLib with great results.
ChaosPandion
+1  A: 

Use System.IO.Directory and System.IO.File classes to enumerate all the files and folders, do it recursively to ensure you get file in subfolders. Once you have all the files zip them one at a time (or use a threadpool) and you should have what you need.

keithwarren7
+1  A: 

If you're on 3.0+, you can use System.IO.Packaging to create zip files.

Jeff Hardy
Actually, System.IO.Packaging is pretty much useless. It's designed for use with XPS-style documents. If you create a .zip file with it, it will add a file named [Content_Types].xml to the root. Also, you will NOT be able to process .zip files that don't contain the .xml file in the root.
Brannon
And the API for zip files is horrendous.
Cheeso
If you can ignore the "Content_Types.xml" file then this is perfect. This is what I use for my projects.
David
Sure, as long as you are only writing .zip files. If you need to read a .zip file then System.IO.Packaging won't work.
Brannon
+3  A: 

There is plenty of documentation on the .zip file format. Wikipedia is a good place to start: http://en.wikipedia.org/wiki/ZIP_file_format.

You can use the System.IO.Compression.DeflateStream for the actual compression, but you'll need a CRC32 implementation, and you'll need to layout the file with the correct headers, etc.

It is a non-trivial amount of work.

You might consider purchasing a commercial .zip library if you are unable to use an open-source library. You should not have any legal issues with using a commercial library**, and the cost to purchase a license is almost certainly cheaper than the cost of developing and testing the library yourself. Also, check around. Your company might have a license for a commercial library already.

**I'm not a lawyer, so check with your legal contact.

Brannon
+1  A: 

You have a few options

1. Use Shell.Application
You can call out to the Shell. In VBScript it looks like this:

dim sa
set sa = CreateObject("Shell.Application")

Dim zip
Set zip = sa.NameSpace(pathToZipFile)

Dim d
Set d = sa.NameSpace(dirToZip)


For Each s In d.items
    WScript.Echo  s
Next


' http://msdn.microsoft.com/en-us/library/bb787866(VS.85).aspx
' ===============================================================
' 2nd arg is a bit field: 
' 4 = do not display a progress box
' 16 = Respond with "Yes to All" for any dialog box that is displayed.
' 128 = Perform the operation on files only if a wildcard file name (*.*) is specified. 
' 256 = Display a progress dialog box but do not show the file names.
' 2048 = Version 4.71. Do not copy the security attributes of the file.
' 4096 = Only operate in the local directory. Don't operate recursively into subdirectories.

WScript.Echo "copying files..."

zip.CopyHere d.items, 4

' CopyHere is asynchronous. Gotta wait til it's done. 
sLoop = 0
Do Until d.Items.Count <= zip.Items.Count
    Wscript.Sleep(1000)
Loop

I don't know if this is accessible from managed code, but I would guess so. It feels sort of hacky to me though.

Also, you need to pre-initialize the zipfile before adding things to it:

Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim file
Set file = fso.CreateTextFile(pathToZipFile)

file.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)

file.Close
Set fso = Nothing
Set file = Nothing

2. Implement it yourself
If you don't want to use Shell.Application, in theory you could create your own zip class implementation without too much trouble, especially if you have limited requirements. The zip format is not super complicated, if you don't implement encryption, zip64, Unicode, high-resolution timestamps, streaming, and so on...

3. Do the legal review, and Re-Use
Rather than spending engineering time developing a new implementation, investigate the implementations that are out there now. Some people worry about the GPL with SharpZipLib. DotNetZip is released under the Microsoft Public License, very permissive and no viral terms.

Cheeso