The attached project is a library that wraps #ZipLib and provides a simple interface so you can compress to and extract from ZIP files with a single method call. I may put it in the UtilityBank eventually, but it's still a work in progress so I'll leave it here for now.
Note that there are methods to compress a single file, a number of files and a folder, both recursively and not. There are also methods to extract all files, a single file or a number of selected files. At this point there is no facility to add files to an existing archive, but that will be added soon.
Note that this library does nothing on its own. It requires the presence of #ZipLib, which you can download from here, to do the grunt work. The project contains a reference to #ZipLib but that will be broken when you try to use it. You will need to remove that reference and add a new one yourself once you have downloaded it.
Feel free to use this code in full or in part in your own applications, but it must be in accordance with the #ZipLib licence. I will be making future updates, including what I mentioned earlier and support for other compression formats. Feel free to post any requests, suggestions or bug reports on this thread, but I make no guarantees about if and when they will be actioned.
The attached project (VS.NET 2003 format) contains no binary files, so you will of course have to compile it before you use it. It also contains no sample project, as I think the exposed methods pretty much speak for themselves. Note that the root folder contains a documentation file named Wunnell.IO.Compression.chm that should tell you everything you need to know. If you have any issues feel free to post here, but again I make no guarantees about if and when I will be able to provide help.
Enjoy!
Updates:
15092005: v1.0.0.1 - fixed bug in Zip.ExtractEntryByName and Zip.ExtractEntriesByName methods, updated documentation to include VB.NET syntax.
Last edited by jmcilhinney; Aug 9th, 2008 at 09:11 PM.
I have fixed a bug in the ExtractEntryByName and ExtractEntriesByName methods and updated the project attached to post #1 to version 1.0.0.1. I have also updated the documentation to include VB.NET syntax. It was my first time using NDoc so I missed that the first time.
I'm a beginner (also in english) ... I've tried to use it but I've some problem with the "ExtractAllEntries" metod... If in the zip file there aren't any foder all works fine, if there are/is the metod apparently doesn't work ...
I'm a beginner (also in english) ... I've tried to use it but I've some problem with the "ExtractAllEntries" metod... If in the zip file there aren't any foder all works fine, if there are/is the metod apparently doesn't work ...
Have you some suggestion?
I just tested it with folders and it worked fine. I created a form with two buttons and added this code:
VB Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim fbd As New FolderBrowserDialog
If fbd.ShowDialog() = Windows.Forms.DialogResult.OK Then
I then created a new folder under My Documents called "Test Folder" and added two new text files and a new folder, accepting the default names. I then opened the subfolder and added a further two text files with default names. I then ran my project, clicked Button1 and selected the "Test Folder" I created. This created a ZIP file under My Documents named "Test Folder.zip", which I opened and can confirm that it contained all the expected files with the expected paths. I then renamed the folder I created to "xText Folder" and clicked Button2. I selected "Test Folder.zip" and it recreated the original folder structure faithfully.
What exactly is happening that shouldn't when you try it? What overload of ExtractAllEntries are you using? Have you read the documentation to make sure that it is creating the folders where you expect? Was this ZIP file created using this library or by some other tool?
Public Overloads Shared Function ExtractEntriesByIndex(ByVal archiveName As String, ByVal destinationFolder As String, _
ByVal indices As Integer(), ByVal includePath As PathType, ByVal overwrite As Boolean, ByVal verify As Boolean) As Boolean
During my test something was going wrong while the code was moving all the temporary files to their final destination.
The "filesExtracted" index was not corectly calculated ... I've thought that the problrm was the istruction:
VB Code:
File.Move(tempName, fileNames(tempName))
when was processing folder an exception was generated and the "filesExtracted" calculation skipped, if that value is different from indices.Length value all the extracted entry are deleted.
Due to this fact I've modified the code adding a condition:
VB Code:
If Not (Len(Path.GetDirectoryName(fileNames(tempName))) = Len(fileNames(tempName)) - 1) Then
You're right ... my post was not very accurate, but I've left that project long time ago and I don't remember exactly what was going wrong...
Using the original Zip.vb I've tryed to Extract the Dir1.zip file that it's just a zip with the following structure:
Dir1
|---Dir1a
| |--New Text Document.txt
|
|---Dir1b
| |--New Text Document.txt
|
|--New Text Document.txt
I've created a button and I've inserted the following code in the click event:
in order to display the exception message I looked for:"File.Move(tempName, fileNames(tempName))" in zip.vb module, after the catch I inserted "e As Exception" and instead of "'Do nothing." I inserted "MsgBox(e.Message)"
After I pushed the button I've got a message :"Cannot create a file when that file already exist."
Due to this fact I've modified the code in this way:
VB Code:
... zip.vb code
If Not (Len(Path.GetDirectoryName(fileNames(tempName))) = Len(fileNames(tempName)) - 1) Then
I think the code here may need to be updated, was trying to use it today and noticed a lot of errors revolving around ZipNameTransform. I believe from looking at the class in the newest release of #ZipLib that ZipNameTransform no longer uses three different transform methods. The only variable that can be passed to it is string TrimPrefix.
I havn't worked out exactly how it should be used now but all the code dealing with New ZipNameTransform(Boolean, String), needs to be modified. Here is a link to the thread I made in VB .NET forum discussing the problem with some of my observations:
Ok think I found a solution to this, they changed it so that the TrimPrefix string is basically allowing you to store as many levels of the path as you determine that you want to.
So here is a simple fix that will only include the highest level of the path if you tell it to include relative path.
This is the new CompressFolder function in Zip.vb
vb Code:
Public Overloads Shared Function CompressFolder(ByVal sourceName As String, _
ByVal archiveName As String, _
ByVal recursive As Boolean, _
ByVal excludeHidden As Boolean, _
ByVal level As CompressionLevel, _
ByVal includePath As PathType, _
ByVal overwrite As Boolean, _
ByVal testData As Boolean) As Boolean
Dim transform As ZipNameTransform
Dim relPath As String
Dim pSplit() As String
Dim i As Integer
If Right(sourceName, 1) = "\" Then sourceName = Left(sourceName, Len(sourceName) - 1)
This might not be the cleanest way to do it but it works. Do about the same for compressFiles, but make sure you are doing it in the right one.
vb Code:
Public Overloads Shared Function CompressFiles(ByVal sourceNames As String(), _
ByVal archiveName As String, _
ByVal level As CompressionLevel, _
ByVal includePath As PathType, _
ByVal overwrite As Boolean, _
ByVal testData As Boolean) As Boolean
Dim transform As ZipNameTransform
Dim relPath As String
Dim pSplit As String()
Dim i As Integer
Dim cRoot As String
cRoot = GetCommonRoot(sourceNames)
If Right(cRoot, 1) = "\" Then cRoot = Left(cRoot, Len(cRoot) - 1)
pSplit = Split(cRoot, "\")
relPath = pSplit(0)
If UBound(pSplit) >= 2 Then
For i = 1 To UBound(pSplit) - 1
relPath = relPath & "\" & pSplit(i)
Next
Else
relPath = relPath & "\"
End If
'Create the appropriate name transform.
Select Case includePath
Case PathType.None
transform = Nothing
Case PathType.Relative
transform = New ZipNameTransform(relPath)
Case PathType.Full
transform = New ZipNameTransform
End Select
Return CompressFiles(sourceNames, _
archiveName, _
level, _
transform, _
overwrite, _
testData)
End Function(sourceNames))
Also you have to go through and any where there is a New ZipNameTransform([True / False) just change it to New ZipNameTransform, I'm not sure what this boolean was representing when this was written but it apparently is not needed anymore.
Again this is just my quick fix, if the original author looks at it again he will probably have a better solution.
Last edited by StevenHickerson; Nov 1st, 2007 at 02:53 PM.
Thanks for the input. It is quite a while since I've looked at this so maybe I will create an updated version soon for the most recent version of #ZipLib.