Zip files in c#
Hi,
Does anyone know of a way to zip files in c#. I tried using sharplib but the compression utility that comes with XP is not able to unzip the files. I need a format that can be unzipped by this and most other compression tools since I am not sure exactly what my users will be using to unzip the files.
Thanks in advance
[328 byte] By [
GBez] at [2007-12-16]
To unzip files in Windows XP, zip files need to have entries that use relative paths.
For example, a zip file containing the following entry cannot be unzip by Windows XP:
c:\Temp\Myfile.txt
However this can:
Temp\Myfile.txt
You need to remove the root of the file name before using it in the ZipEntry, I use a function similar to this to do that:
| |
public static string RemovePathRoot(string path) { string root = Path.GetPathRoot(path); return path.Substring(root.Length); }
|
I have quite happily used SharpZipLib and Windows XP together.
If you're interrested in paying for the zip component, i can reccomend xceedsoft Zip for .NET (
http://www.xceedsoft.com) . They have a rather good implementation of Zip and an very good file system abstraction layer.
Do you mean I should be specifying a relative path for the zip file to be created in?
My code is as follows but I still cant read the file using XP's compression utility:
Note: These are my command line parameters that I start the app with:
"\Documents and Settings\gbezuidenhout\My Documents\ZipTest" "\Documents and Settings\gbezuidenhout\My Documents\Zipped.zip"
string[] filenames = Directory.GetFiles(args[0]);
Crc32 crc = new Crc32();
ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));
s.SetLevel(6); // 0 - store only to 9 - means best compression
foreach (string file in filenames) { FileStream fs = File.OpenRead(file);
byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length);
ZipEntry entry =
new ZipEntry(file); entry.DateTime = DateTime.Now;
// set Size and the crc, because the information // about the size and crc should be stored in the header // if it is not set it is automatically written in the footer. // (in this case size == crc == -1 in the header) // Some ZIP programs have problems with zip files that don't store // the size and crc in the header. entry.Size = fs.Length;
fs.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
s.PutNextEntry(entry);
s.Write(buffer, 0, buffer.Length);
}
s.Finish();
s.Close();
No, the files within the ZipEntry need to be relative.
For example:
This line:
| | ZipEntry entry = new ZipEntry(file); |
Should be changed to call my method above:
| | ZipEntry entry = new ZipEntry(RemovePathRoot(file)); |
That works perfect, thanks. The only question I have now though is if I do use XP to open the file, it shows the entire directory structure down to the file that was zipped i.e. When you open the file as in the above example, you first see the folder Documents and Settings, then after going into that folder, gbezuidenhout all the way until you get to the file. I assume that is because the path property of the zipped file is that directory structure so I guess my question is, is there a way setting that property of the file to nothing after it has been zipped so that as soon as the user opens the file, he only sees the file that was zipped. I dont really want him to see the directory structure of the machine that the file was zipped on.
Yes.
Use Path.GetFileName() instead of RemovePathRoot() above.
Sorted, thanks very much for your help.
The J# solution is broke because the required assembly don't ship with .NET 2.0 beta 2. I don't want to use the sharp lib when the basic functionality is available in the framework. I wonder how hard it is to zip/unzip a folder using
Sytem.IO.Compression. So far there is no sample code available, at least I didn't find any sample code.
eclipse2k wrote: |
|
I don't think this information will help me to zip a dir that can be unziped with WinRar and Co. because zip and gzip a different things.
stax0711 wrote: |
The J# solution is broke because the required assembly don't ship with .NET 2.0 beta 2. I don't want to use the sharp lib when the basic functionality is available in the framework. I wonder how hard it is to zip/unzip a folder using Sytem.IO.Compression. So far there is no sample code available, at least I didn't find any sample code.
|
|
You need to reproduce exactly what the SharpZibLib is doing anyway, so is it worth it?
stax0711 wrote: |
| I wonder how hard it is to zip/unzip a folder using Sytem.IO.Compression. |
|
You can do it using the System.IO.Compression namespace BUT you have to add a "small" payload.
The Framework compression classes handle the ZIP-age of the data stream but you have to handle the ZIP file format by yourself! :) it has more than the zipped-data (headers, checksums, directory structure and so on)
I actually use this to unzip a single file.
| | 'Data Array contains the .zip fileDim Start, Lenght As Integer Start = &H1E Start += BitConverter.ToInt16(Data, &H1A) Start += BitConverter.ToInt16(Data, &H1C) Lenght = BitConverter.ToInt32(Data, &H12) DataStream = New MemoryStream(Data, Start, Lenght) Dim UncompStream As New MemoryStream Dim DecStream As New Compression.DeflateStream(DataStream, Compression.CompressionMode.Decompress, True) Dim Value As Integer = DecStream.ReadByte Do Until Value = -1 UncompStream.WriteByte(CByte(Value)) Value = DecStream.ReadByte Loop DataStream.Close() DataStream = UncompStream |
You can find out more amour the .ZIP file format with any RFC about it on the web (I don't remember the rfc number. Simply open google and search zip file format structure pk deflated stored)
Or.. for a MOOOOORE complete (and complex) document look here.