Ability to re-name a file within a zip archive?

Jul 15, 2008 at 4:30 PM
I have a need to simply re-name a file (actually all the files) in a zip archive.  I would rather not deflate, rename, and then re-enflate if possible; as the application I'm working on will need to rename files within thousands of zip files. 

I've looked through the documentation for this library and it appears the name property for a zip entry is read-only.  Is there a way to use this library to accomplish what I'm trying to do?  If not, any ideas?

Thanks!
Coordinator
Jul 16, 2008 at 4:04 PM
Edited Feb 20, 2009 at 5:44 PM

Hmm, yes, the entry name is currenty a read only property.

Of course, it's just software  - it would be possible to modify the library to do renames within zipfiles.  But... the rename is already possible the way you described.  It's pretty simple.  Yes it involves decompressing and then recompressing, which consumes CPU cycles.  Is that really a  problem?  Do you have a time constraint during which you need to modify the 1000's of files? Are you CPU constrained? Are you dealing with a time latency thing?

Changing the code to support renames would likely involve a change only to the ZipEntry class.  You could expose a new method .Rename(), and in it mark the entry changed so that it gets re-written when a .Write() (ZipFile.Save()) is called.  It would still involve creating a new zipfile, re-writing the data for all entries in the zip (not just the renamed one), renaming the temp zipfile, and removing the original one.  There'd still be all that file i/o, it is unavoidable given the zip format with the CRCs and so on.  The decompress/recompress wouldn't happen as the file data itself would not change.

This kind of change would eliminate the need to extract the entry to a real file, then rename it, then re-zip it. 
-----------
UPDATE, February 2009: The v1.7 library includes a rename capability.

Jul 16, 2008 at 7:40 PM
Thanks for this information.  I think I am going to change my approach a little and just go ahead and decompress the zip archive, rename the files, and then recreate the archive.  It may take a while to do this for 80,000 files; but it should not be something that must be done regularly, so CPU cycles and disc access performance may not be a real issue.

I could modify he ZipEntry class to expose the Rename() method, but I don't feel this would offer enough of a performance advantage to make it worth the effort.

Thanks very much for the insight, fast reponse, and for the great work to create this library.
Feb 10, 2009 at 8:21 PM
I had a similar situation where I needed to rename files (stored with guid names) with a user friendly name and I used the following approach (streams). 

For each source file that needed zipped-
1. Opened a FileStream and read the contents of the file.
2. Converted the FileStream into a MemoryStream.
3. Added the memoryStream using zip.AddFileStream(UserFriendlyFileName, string.Empty, ConvertedMemoryStream)

and then called Zip.Save();

Best regards,
Kaushal
Coordinator
Feb 11, 2009 at 5:54 AM
Kaushal, what you describe will work.  But, you don't need to go to the trouble if you use the v1.7 library.
Wth v1.7, renaming is very simple.  The FileName property on the ZipEntry is read/write.  Setting the FileName effectively renames the entry.  The doc describes this. Also, there are examples in the help file.  As well as on this site (http://www.codeplex.com/DotNetZip/Wiki/View.aspx?title=Examples)

Like this:
  using (ZipFile zip = ZipFile.Read("ExistingArchive.zip"))
  {
    // update
    zip.UpdateItem("Portfolio.doc"); 
    // remove
    zip["OldData.txt"].RemoveEntry();
    // rename:
    zip["Internationalization.doc"].FileName = "i18n.doc";
    // add a comment to the archive
    zip.Comment = "This zip archive was updated " + System.DateTime.ToString("G"); 
    zip.Save();
  }
Feb 18, 2009 at 5:12 PM
Cheeso- Thanks so much for the read/write enhancement. That will certainly shrink my code to a great extent!!

Best
Kaushal