Class ZipFile
The ZipFile type represents a zip archive file.
[Guid("ebc25cf6-9120-4283-b972-0e5520d00005")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
public class ZipFile : IEnumerable<ZipEntry>, IEnumerable, IDisposable
- Inheritance
-
ZipFile
- Implements
- Inherited Members
- Extension Methods
Remarks
This is the main type in the DotNetZip class library. This class reads and writes zip files, as defined in the specification for zip files described by PKWare. The compression for this implementation is provided by a managed-code version of Zlib, included with DotNetZip in the classes in the Ionic.Zlib namespace.
This class provides a general purpose zip file capability. Use it to read,
create, or update zip files. When you want to create zip files using a
Stream type to write the zip file, you may want to consider the ZipOutputStream class.
Both the ZipOutputStream class and the ZipFile class can
be used to create zip files. Both of them support many of the common zip
features, including Unicode, different compression methods and levels,
and ZIP64. They provide very similar performance when creating zip
files.
The ZipFile class is generally easier to use than
ZipOutputStream and should be considered a higher-level interface. For
example, when creating a zip file via calls to the PutNextEntry() and
Write() methods on the ZipOutputStream class, the caller is
responsible for opening the file, reading the bytes from the file, writing
those bytes into the ZipOutputStream, setting the attributes on the
ZipEntry, and setting the created, last modified, and last accessed
timestamps on the zip entry. All of these things are done automatically by a
call to ZipFile.AddFile().
For this reason, the ZipOutputStream is generally recommended for use
only when your application emits arbitrary data, not necessarily data from a
filesystem file, directly into a zip file, and does so using a Stream
metaphor.
Aside from the differences in programming model, there are other differences in capability between the two classes.
-
ZipFilecan be used to read and extract zip files, in addition to creating zip files.ZipOutputStreamcannot read zip files. If you want to use a stream to read zip files, check out the ZipInputStream class. -
ZipOutputStreamdoes not support the creation of segmented or spanned zip files. -
ZipOutputStreamcannot produce a self-extracting archive.
Be aware that the ZipFile class implements the IDisposable interface. In order for ZipFile to
produce a valid zip file, you use use it within a using clause (Using
in VB), or call the Dispose() method explicitly. See the examples
for how to employ a using clause.
Constructors
ZipFile()
Create a zip file, without specifying a target filename or stream to save to.
public ZipFile()
Examples
This example creates a Zip archive called Backup.zip, containing all the files in the directory DirectoryToZip. Files within subdirectories are not zipped up.
using (ZipFile zip = new ZipFile())
{
// Store all files found in the top level directory, into the zip archive.
// note: this code does not recurse subdirectories!
String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
zip.AddFiles(filenames, "files");
zip.Save("Backup.zip");
}
Using zip As New ZipFile
' Store all files found in the top level directory, into the zip archive.
' note: this code does not recurse subdirectories!
Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
zip.AddFiles(filenames, "files")
zip.Save("Backup.zip")
End Using
Remarks
See the documentation on the ZipFile
constructor that accepts a single string argument for basic
information on all the ZipFile constructors.
After instantiating with this constructor and adding entries to the
archive, the application should call Save(string) or
Save(Stream) to save to a file or a
stream, respectively. The application can also set the Name
property and then call the no-argument Save() method. (This
is the preferred approach for applications that use the library through
COM interop.) If you call the no-argument Save() method
without having set the Name of the ZipFile, either through
the parameterized constructor or through the explicit property , the
Save() will throw, because there is no place to save the file.
Instances of the ZipFile class are not multi-thread safe. You may
have multiple threads that each use a distinct ZipFile instance, or
you can synchronize multi-thread access to a single instance.
ZipFile(string)
Creates a new ZipFile instance, using the specified filename.
public ZipFile(string fileName)
Parameters
fileNamestringThe filename to use for the new zip archive.
Examples
This example shows how to create a zipfile, and add a few files into it.
String ZipFileToCreate = "archive1.zip";
String DirectoryToZip = "c:\\reports";
using (ZipFile zip = new ZipFile())
{
// Store all files found in the top level directory, into the zip archive.
String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
zip.AddFiles(filenames, "files");
zip.Save(ZipFileToCreate);
}
Dim ZipFileToCreate As String = "archive1.zip"
Dim DirectoryToZip As String = "c:\reports"
Using zip As ZipFile = New ZipFile()
Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
zip.AddFiles(filenames, "files")
zip.Save(ZipFileToCreate)
End Using
Remarks
Applications can use this constructor to create a new ZipFile for writing, or to slurp in an existing zip archive for read and update purposes.
To create a new zip archive, an application can call this constructor,
passing the name of a file that does not exist. The name may be a fully
qualified path. Then the application can add directories or files to the
ZipFile via AddDirectory(), AddFile(), AddItem()
and then write the zip archive to the disk by calling Save(). The
zip file is not actually opened and written to the disk until the
application calls ZipFile.Save(). At that point the new zip file
with the given name is created.
If you won't know the name of the Zipfile until the time you call
ZipFile.Save(), or if you plan to save to a stream (which has no
name), then you should use the no-argument constructor.
The application can also call this constructor to read an existing zip
archive. passing the name of a valid zip file that does exist. But, it's
better form to use the static Read(string) method,
passing the name of the zip file, because using ZipFile.Read() in
your code communicates very clearly what you are doing. In either case,
the file is then read into the ZipFile instance. The app can then
enumerate the entries or can modify the zip file, for example adding
entries, removing entries, changing comments, and so on.
One advantage to this parameterized constructor: it allows applications to use the same code to add items to a zip archive, regardless of whether the zip file exists.
Instances of the ZipFile class are not multi-thread safe. You may
not party on a single instance with multiple threads. You may have
multiple threads that each use a distinct ZipFile instance, or you
can synchronize multi-thread access to a single instance.
By the way, since DotNetZip is so easy to use, don't you think you should donate $5 or $10?
Exceptions
- ZipException
Thrown if name refers to an existing file that is not a valid zip file.
ZipFile(string, TextWriter)
Creates a new ZipFile instance, using the specified name for the
filename, and the specified status message writer.
public ZipFile(string fileName, TextWriter statusMessageWriter)
Parameters
fileNamestringThe filename to use for the new zip archive.
statusMessageWriterTextWriterA TextWriter to use for writing verbose status messages.
Examples
using (ZipFile zip = new ZipFile("Backup.zip", Console.Out))
{
// Store all files found in the top level directory, into the zip archive.
// note: this code does not recurse subdirectories!
// Status messages will be written to Console.Out
String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
zip.AddFiles(filenames);
zip.Save();
}
Using zip As New ZipFile("Backup.zip", Console.Out)
' Store all files found in the top level directory, into the zip archive.
' note: this code does not recurse subdirectories!
' Status messages will be written to Console.Out
Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
zip.AddFiles(filenames)
zip.Save()
End Using
Remarks
See the documentation on the ZipFile
constructor that accepts a single string argument for basic
information on all the ZipFile constructors.
This version of the constructor allows the caller to pass in a TextWriter,
to which verbose messages will be written during extraction or creation of
the zip archive. A console application may wish to pass
System.Console.Out to get messages on the Console. A graphical or headless
application may wish to capture the messages in a different
TextWriter, for example, a StringWriter, and then display
the messages in a TextBox, or generate an audit log of ZipFile operations.
To encrypt the data for the files added to the ZipFile instance,
set the Password property after creating the ZipFile instance.
Instances of the ZipFile class are not multi-thread safe. You may
not party on a single instance with multiple threads. You may have
multiple threads that each use a distinct ZipFile instance, or you
can synchronize multi-thread access to a single instance.
Exceptions
- ZipException
Thrown if name refers to an existing file that is not a valid zip file.
ZipFile(string, TextWriter, Encoding)
Creates a new ZipFile instance, using the specified name for the
filename, the specified status message writer, and the specified Encoding.
public ZipFile(string fileName, TextWriter statusMessageWriter, Encoding encoding)
Parameters
fileNamestringThe filename to use for the new zip archive.
statusMessageWriterTextWriterA TextWriter to use for writing verbose status messages.
encodingEncodingThe Encoding is used as the default alternate encoding for entries with filenames or comments that cannot be encoded with the IBM437 code page.
Remarks
This constructor works like the ZipFile constructor that accepts a single string argument. See that reference for detail on what this constructor does.
This version of the constructor allows the caller to pass in a
TextWriter, and an Encoding. The TextWriter will collect
verbose messages that are generated by the library during extraction or
creation of the zip archive. A console application may wish to pass
System.Console.Out to get messages on the Console. A graphical or
headless application may wish to capture the messages in a different
TextWriter, for example, a StringWriter, and then display
the messages in a TextBox, or generate an audit log of
ZipFile operations.
The Encoding is used as the default alternate encoding for entries
with filenames or comments that cannot be encoded with the IBM437 code
page. This is a equivalent to setting the ProvisionalAlternateEncoding property on the ZipFile
instance after construction.
To encrypt the data for the files added to the ZipFile instance,
set the Password property after creating the ZipFile
instance.
Instances of the ZipFile class are not multi-thread safe. You may
not party on a single instance with multiple threads. You may have
multiple threads that each use a distinct ZipFile instance, or you
can synchronize multi-thread access to a single instance.
Exceptions
- ZipException
Thrown if
fileNamerefers to an existing file that is not a valid zip file.
ZipFile(string, Encoding)
Creates a new ZipFile instance, using the specified name for the
filename, and the specified Encoding.
public ZipFile(string fileName, Encoding encoding)
Parameters
fileNamestringThe filename to use for the new zip archive.
encodingEncodingThe Encoding is used as the default alternate encoding for entries with filenames or comments that cannot be encoded with the IBM437 code page.
Remarks
See the documentation on the ZipFile
constructor that accepts a single string argument for basic
information on all the ZipFile constructors.
The Encoding is used as the default alternate encoding for entries with
filenames or comments that cannot be encoded with the IBM437 code page.
This is equivalent to setting the ProvisionalAlternateEncoding property on the ZipFile
instance after construction.
Instances of the ZipFile class are not multi-thread safe. You may
not party on a single instance with multiple threads. You may have
multiple threads that each use a distinct ZipFile instance, or you
can synchronize multi-thread access to a single instance.
Exceptions
- ZipException
Thrown if name refers to an existing file that is not a valid zip file.
ZipFile(Encoding)
Create a zip file, specifying a text Encoding, but without specifying a target filename or stream to save to.
public ZipFile(Encoding encoding)
Parameters
encodingEncodingThe Encoding is used as the default alternate encoding for entries with filenames or comments that cannot be encoded with the IBM437 code page.
Remarks
See the documentation on the ZipFile
constructor that accepts a single string argument for basic
information on all the ZipFile constructors.
Fields
BufferSizeDefault
Default size of the buffer used for IO.
public static readonly int BufferSizeDefault
Field Value
Properties
AddDirectoryWillTraverseReparsePoints
Indicates whether NTFS Reparse Points, like junctions, should be
traversed during calls to AddDirectory().
public bool AddDirectoryWillTraverseReparsePoints { get; set; }
Property Value
Examples
using (var zip = new ZipFile())
{
zip.AddDirectoryWillTraverseReparsePoints = false;
zip.AddDirectory(dirToZip,"fodder");
zip.Save(zipFileToCreate);
}
Remarks
By default, calls to AddDirectory() will traverse NTFS reparse points, like mounted volumes, and directory junctions. An example of a junction is the "My Music" directory in Windows Vista. In some cases you may not want DotNetZip to traverse those directories. In that case, set this property to false.
AlternateEncoding
A Text Encoding to use when encoding the filenames and comments for all the ZipEntry items, during a ZipFile.Save() operation.
public Encoding AlternateEncoding { get; set; }
Property Value
Remarks
Whether the encoding specified here is used during the save depends on AlternateEncodingUsage.
AlternateEncodingUsage
A flag that tells if and when this instance should apply AlternateEncoding to encode the filenames and comments associated to of ZipEntry objects contained within this instance.
public ZipOption AlternateEncodingUsage { get; set; }
Property Value
BufferSize
Size of the IO buffer used while saving.
public int BufferSize { get; set; }
Property Value
Examples
This example shows how you might set a large buffer size for efficiency when dealing with zip entries that are larger than 1gb.
using (ZipFile zip = new ZipFile())
{
zip.SaveProgress += this.zip1_SaveProgress;
zip.AddDirectory(directoryToZip, "");
zip.UseZip64WhenSaving = Zip64Option.Always;
zip.BufferSize = 65536*8; // 65536 * 8 = 512k
zip.Save(ZipFileToCreate);
}
Remarks
First, let me say that you really don't need to bother with this. It is here to allow for optimizations that you probably won't make! It will work fine if you don't set or get this property at all. Ok?
Now that we have that out of the way, the fine print: This property affects the size of the buffer that is used for I/O for each entry contained in the zip file. When a file is read in to be compressed, it uses a buffer given by the size here. When you update a zip file, the data for unmodified entries is copied from the first zip file to the other, through a buffer given by the size here.
Changing the buffer size affects a few things: first, for larger buffer
sizes, the memory used by the ZipFile, obviously, will be larger
during I/O operations. This may make operations faster for very much
larger files. Last, for any given entry, when you use a larger buffer
there will be fewer progress events during I/O operations, because there's
one progress event generated for each time the buffer is filled and then
emptied.
The default buffer size is 8k. Increasing the buffer size may speed things up as you compress larger files. But there are no hard-and-fast rules here, eh? You won't know til you test it. And there will be a limit where ever larger buffers actually slow things down. So as I said in the beginning, it's probably best if you don't set or get this property at all.
CaseSensitiveRetrieval
Indicates whether to perform case-sensitive matching on the filename when retrieving entries in the zipfile via the string-based indexer.
public bool CaseSensitiveRetrieval { get; set; }
Property Value
Remarks
The default value is false, which means don't do case-sensitive
matching. In other words, retrieving zip["ReadMe.Txt"] is the same as
zip["readme.txt"]. It really makes sense to set this to true only
if you are not running on Windows, which has case-insensitive
filenames. But since this library is not built for non-Windows platforms,
in most cases you should just leave this property alone.
CodecBufferSize
Size of the work buffer to use for the ZLIB codec during compression.
public int CodecBufferSize { get; set; }
Property Value
Remarks
When doing ZLIB or Deflate compression, the library fills a buffer,
then passes it to the compressor for compression. Then the library
reads out the compressed bytes. This happens repeatedly until there
is no more uncompressed data to compress. This property sets the
size of the buffer that will be used for chunk-wise compression. In
order for the setting to take effect, your application needs to set
this property before calling one of the ZipFile.Save()
overloads.
Setting this affects the performance and memory efficiency of compression and decompression. For larger files, setting this to a larger size may improve compression performance, but the exact numbers vary depending on available memory, the size of the streams you are compressing, and a bunch of other variables. I don't have good firm recommendations on how to set it. You'll have to test it yourself. Or just leave it alone and accept the default.
Comment
A comment attached to the zip archive.
public string Comment { get; set; }
Property Value
Remarks
This property is read/write. It allows the application to specify a
comment for the ZipFile, or read the comment for the
ZipFile. After setting this property, changes are only made
permanent when you call a Save() method.
According to PKWARE's zip specification, the comment is not encrypted, even if there is a password set on the zip file.
The specification does not describe how to indicate the encoding used
on a comment string. Many "compliant" zip tools and libraries use
IBM437 as the code page for comments; DotNetZip, too, follows that
practice. On the other hand, there are situations where you want a
Comment to be encoded with something else, for example using code page
950 "Big-5 Chinese". To fill that need, DotNetZip will encode the
comment following the same procedure it follows for encoding
filenames: (a) if AlternateEncodingUsage is
Never, it uses the default encoding (IBM437). (b) if AlternateEncodingUsage is Always, it always uses the
alternate encoding (AlternateEncoding). (c) if AlternateEncodingUsage is AsNecessary, it uses the
alternate encoding only if the default encoding is not sufficient for
encoding the comment - in other words if decoding the result does not
produce the original string. This decision is taken at the time of
the call to ZipFile.Save().
When creating a zip archive using this library, it is possible to change
the value of AlternateEncoding between each
entry you add, and between adding entries and the call to
Save(). Don't do this. It will likely result in a zip file that is
not readable by any tool or application. For best interoperability, leave
AlternateEncoding alone, or specify it only
once, before adding any entries to the ZipFile instance.
CompressionLevel
Sets the compression level to be used for entries subsequently added to the zip archive.
public CompressionLevel CompressionLevel { get; set; }
Property Value
Remarks
Varying the compression level used on entries can affect the size-vs-speed tradeoff when compression and decompressing data streams or files.
As with some other properties on the ZipFile class, like Password, Encryption, and ZipErrorAction, setting this property on a ZipFile
instance will cause the specified CompressionLevel to be used on all
ZipEntry items that are subsequently added to the
ZipFile instance. If you set this property after you have added
items to the ZipFile, but before you have called Save(),
those items will not use the specified compression level.
If you do not set this property, the default compression level is used,
which normally gives a good balance of compression efficiency and
compression speed. In some tests, using BestCompression can
double the time it takes to compress, while delivering just a small
increase in compression efficiency. This behavior will vary with the
type of data you compress. If you are in doubt, just leave this setting
alone, and accept the default.
CompressionMethod
The compression method for the zipfile.
public CompressionMethod CompressionMethod { get; set; }
Property Value
Remarks
By default, the compression method is CompressionMethod.Deflate.
- See Also
Count
Returns the number of entries in the Zip archive.
public int Count { get; }
Property Value
DefaultEncoding
The default text encoding used in zip archives. It is numeric 437, also known as IBM437.
public static Encoding DefaultEncoding { get; set; }
Property Value
- See Also
EmitTimesInUnixFormatWhenSaving
Specifies whether the Creation, Access, and Modified times for entries added to the zip file will be emitted in "Unix(tm) format" when the zip archive is saved.
public bool EmitTimesInUnixFormatWhenSaving { get; set; }
Property Value
Remarks
An application creating a zip archive can use this flag to explicitly
specify that the file times for the entries should or should not be stored
in the zip archive in the format used by Unix. By default this flag is
false, meaning the Unix-format times are not stored in the zip
archive.
When adding an entry from a file or directory, the Creation (CreationTime), Access (AccessedTime), and Modified (ModifiedTime) times for the given entry are automatically set from the filesystem values. When adding an entry from a stream or string, all three values are implicitly set to DateTime.Now. Applications can also explicitly set those times by calling SetEntryTimes(DateTime, DateTime, DateTime).
PKWARE's zip specification describes multiple ways to format these times in a zip file. One is the format Windows applications normally use: 100ns ticks since January 1, 1601 UTC. The other is a format Unix applications typically use: seconds since January 1, 1970 UTC. Each format can be stored in an "extra field" in the zip entry when saving the zip archive. The former uses an extra field with a Header Id of 0x000A, while the latter uses a header ID of 0x5455, although you probably don't need to know that.
Not all tools and libraries can interpret these fields. Windows compressed folders is one that can read the Windows Format timestamps, while I believe the Infozip tools can read the Unix format timestamps. Some tools and libraries may be able to read only one or the other. DotNetZip can read or write times in either or both formats.
The times stored are taken from ModifiedTime, AccessedTime, and CreationTime.
This property is not mutually exclusive of the EmitTimesInWindowsFormatWhenSaving property. It is possible and legal and valid to produce a zip file that contains timestamps encoded in the Unix format as well as in the Windows format, in addition to the LastModified time attached to each entry in the zip archive, a time that is always stored in "DOS format". And, notwithstanding the names PKWare uses for these time formats, any of them can be read and written by any computer, on any operating system. But, there are no guarantees that a program running on Mac or Linux will gracefully handle a zip file with "Windows" formatted times, or that an application that does not use DotNetZip but runs on Windows will be able to handle file times in Unix format.
When in doubt, test. Sorry, I haven't got a complete list of tools and which sort of timestamps they can use and will tolerate. If you get any good information and would like to pass it on, please do so and I will include that information in this documentation.
- See Also
EmitTimesInWindowsFormatWhenSaving
Specifies whether the Creation, Access, and Modified times for entries added to the zip file will be emitted in “Windows format” when the zip archive is saved.
public bool EmitTimesInWindowsFormatWhenSaving { get; set; }
Property Value
Examples
This example shows how to save a zip file that contains file timestamps in a format normally used by Unix.
using (var zip = new ZipFile())
{
// produce a zip file the Mac will like
zip.EmitTimesInWindowsFormatWhenSaving = false;
zip.EmitTimesInUnixFormatWhenSaving = true;
zip.AddDirectory(directoryToZip, "files");
zip.Save(outputFile);
}
Using zip As New ZipFile
'' produce a zip file the Mac will like
zip.EmitTimesInWindowsFormatWhenSaving = False
zip.EmitTimesInUnixFormatWhenSaving = True
zip.AddDirectory(directoryToZip, "files")
zip.Save(outputFile)
End Using
Remarks
An application creating a zip archive can use this flag to explicitly
specify that the file times for the entries should or should not be stored
in the zip archive in the format used by Windows. By default this flag is
true, meaning the Windows-format times are stored in the zip
archive.
When adding an entry from a file or directory, the Creation (CreationTime), Access (AccessedTime), and Modified (ModifiedTime) times for the given entry are
automatically set from the filesystem values. When adding an entry from a
stream or string, all three values are implicitly set to
DateTime.Now. Applications can also explicitly set those times by
calling SetEntryTimes(DateTime, DateTime, DateTime).
PKWARE's zip specification describes multiple ways to format these times in a zip file. One is the format Windows applications normally use: 100ns ticks since January 1, 1601 UTC. The other is a format Unix applications typically use: seconds since January 1, 1970 UTC. Each format can be stored in an "extra field" in the zip entry when saving the zip archive. The former uses an extra field with a Header Id of 0x000A, while the latter uses a header ID of 0x5455, although you probably don't need to know that.
Not all tools and libraries can interpret these fields. Windows compressed folders is one that can read the Windows Format timestamps, while I believe the Infozip tools can read the Unix format timestamps. Some tools and libraries may be able to read only one or the other. DotNetZip can read or write times in either or both formats.
The times stored are taken from ModifiedTime, AccessedTime, and CreationTime.
The value set here applies to all entries subsequently added to the
ZipFile.
This property is not mutually exclusive of the EmitTimesInUnixFormatWhenSaving property. It is possible and legal and valid to produce a zip file that contains timestamps encoded in the Unix format as well as in the Windows format, in addition to the LastModified time attached to each entry in the archive, a time that is always stored in "DOS format". And, notwithstanding the names PKWare uses for these time formats, any of them can be read and written by any computer, on any operating system. But, there are no guarantees that a program running on Mac or Linux will gracefully handle a zip file with "Windows" formatted times, or that an application that does not use DotNetZip but runs on Windows will be able to handle file times in Unix format.
When in doubt, test. Sorry, I haven't got a complete list of tools and which sort of timestamps they can use and will tolerate. If you get any good information and would like to pass it on, please do so and I will include that information in this documentation.
- See Also
Encryption
The Encryption to use for entries added to the ZipFile.
public EncryptionAlgorithm Encryption { get; set; }
Property Value
Examples
This example creates a zip archive that uses encryption, and then extracts entries from the archive. When creating the zip archive, the ReadMe.txt file is zipped without using a password or encryption. The other files use encryption.
// Create a zip archive with AES Encryption.
using (ZipFile zip = new ZipFile())
{
zip.AddFile("ReadMe.txt");
zip.Encryption= EncryptionAlgorithm.WinZipAes256;
zip.Password= "Top.Secret.No.Peeking!";
zip.AddFile("7440-N49th.png");
zip.AddFile("2008-Regional-Sales-Report.pdf");
zip.Save("EncryptedArchive.zip");
}
// Extract a zip archive that uses AES Encryption.
// You do not need to specify the algorithm during extraction.
using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
{
zip.Password= "Top.Secret.No.Peeking!";
zip.ExtractAll("extractDirectory");
}
' Create a zip that uses Encryption.
Using zip As New ZipFile()
zip.Encryption= EncryptionAlgorithm.WinZipAes256
zip.Password= "Top.Secret.No.Peeking!"
zip.AddFile("ReadMe.txt")
zip.AddFile("7440-N49th.png")
zip.AddFile("2008-Regional-Sales-Report.pdf")
zip.Save("EncryptedArchive.zip")
End Using
' Extract a zip archive that uses AES Encryption.
' You do not need to specify the algorithm during extraction.
Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
zip.Password= "Top.Secret.No.Peeking!"
zip.ExtractAll("extractDirectory")
End Using
Remarks
Set this when creating a zip archive, or when updating a zip archive. The
specified Encryption is applied to the entries subsequently added to the
ZipFile instance. Applications do not need to set the
Encryption property when reading or extracting a zip archive.
If you set this to something other than EncryptionAlgorithm.None, you will also need to set the Password.
As with some other properties on the ZipFile class, like Password and CompressionLevel, setting this
property on a ZipFile instance will cause the specified
EncryptionAlgorithm to be used on all ZipEntry items
that are subsequently added to the ZipFile instance. In other
words, if you set this property after you have added items to the
ZipFile, but before you have called Save(), those items will
not be encrypted or protected with a password in the resulting zip
archive. To get a zip archive with encrypted entries, set this property,
along with the Password property, before calling
AddFile, AddItem, or AddDirectory (etc.) on the
ZipFile instance.
If you read a ZipFile, you can modify the Encryption on an
encrypted entry, only by setting the Encryption property on the
ZipEntry itself. Setting the Encryption property on the
ZipFile, once it has been created via a call to
ZipFile.Read(), does not affect entries that were previously read.
For example, suppose you read a ZipFile, and there is an encrypted
entry. Setting the Encryption property on that ZipFile and
then calling Save() on the ZipFile does not update the
Encryption used for the entries in the archive. Neither is an
exception thrown. Instead, what happens during the Save() is that
all previously existing entries are copied through to the new zip archive,
with whatever encryption and password that was used when originally
creating the zip archive. Upon re-reading that archive, to extract
entries, applications should use the original password or passwords, if
any.
Suppose an application reads a ZipFile, and there is an encrypted
entry. Setting the Encryption property on that ZipFile and
then adding new entries (via AddFile(), AddEntry(), etc)
and then calling Save() on the ZipFile does not update the
Encryption on any of the entries that had previously been in the
ZipFile. The Encryption property applies only to the
newly-added entries.
- See Also
Entries
Returns the readonly collection of entries in the Zip archive.
public ICollection<ZipEntry> Entries { get; }
Property Value
Remarks
If there are no entries in the current ZipFile, the value returned is a
non-null zero-element collection. If there are entries in the zip file,
the elements are returned in no particular order.
This is the implied enumerator on the ZipFile class. If you use a
ZipFile instance in a context that expects an enumerator, you will
get this collection.
- See Also
EntriesSorted
Returns a readonly collection of entries in the Zip archive, sorted by FileName.
public ICollection<ZipEntry> EntriesSorted { get; }
Property Value
Examples
This example fills a Windows Forms ListView with the entries in a zip file.
using (ZipFile zip = ZipFile.Read(zipFile))
{
foreach (ZipEntry entry in zip.EntriesSorted)
{
ListViewItem item = new ListViewItem(n.ToString());
n++;
string[] subitems = new string[] {
entry.FileName.Replace("/","\\"),
entry.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
entry.UncompressedSize.ToString(),
String.Format("{0,5:F0}%", entry.CompressionRatio),
entry.CompressedSize.ToString(),
(entry.UsesEncryption) ? "Y" : "N",
String.Format("{0:X8}", entry.Crc)};
foreach (String s in subitems)
{
ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem();
subitem.Text = s;
item.SubItems.Add(subitem);
}
this.listView1.Items.Add(item);
}
}
Remarks
If there are no entries in the current ZipFile, the value returned
is a non-null zero-element collection. If there are entries in the zip
file, the elements are returned sorted by the name of the entry.
- See Also
EntryFileNames
The list of filenames for the entries contained within the zip archive.
public ICollection<string> EntryFileNames { get; }
Property Value
- ICollection<string>
The list of strings for the filenames contained within the Zip archive.
Examples
This example shows one way to test if a filename is already contained within a zip archive.
String zipFileToRead= "PackedDocuments.zip";
string candidate = "DatedMaterial.xps";
using (ZipFile zip = new ZipFile(zipFileToRead))
{
if (zip.EntryFilenames.Contains(candidate))
Console.WriteLine("The file '{0}' exists in the zip archive '{1}'",
candidate,
zipFileName);
else
Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'",
candidate,
zipFileName);
Console.WriteLine();
}
Dim zipFileToRead As String = "PackedDocuments.zip"
Dim candidate As String = "DatedMaterial.xps"
Using zip As ZipFile.Read(ZipFileToRead)
If zip.EntryFilenames.Contains(candidate) Then
Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", _
candidate, _
zipFileName)
Else
Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", _
candidate, _
zipFileName)
End If
Console.WriteLine
End Using
Remarks
According to the ZIP specification, the names of the entries use forward slashes in pathnames. If you are scanning through the list, you may have to swap forward slashes for backslashes.
- See Also
ExtractExistingFile
The action the library should take when extracting a file that already exists.
public ExtractExistingFileAction ExtractExistingFile { get; set; }
Property Value
Remarks
This property affects the behavior of the Extract methods (one of the
Extract() or ExtractWithPassword() overloads), when
extraction would would overwrite an existing filesystem file. If you do
not set this property, the library throws an exception when extracting an
entry would overwrite an existing file.
This property has no effect when extracting to a stream, or when the file to be extracted does not already exist.
- See Also
FlattenFoldersOnExtract
Indicates whether extracted files should keep their paths as stored in the zip archive.
public bool FlattenFoldersOnExtract { get; set; }
Property Value
Remarks
This property affects Extraction. It is not used when creating zip archives.
With this property set to false, the default, extracting entries
from a zip file will create files in the filesystem that have the full
path associated to the entry within the zip file. With this property set
to true, extracting entries from the zip file results in files
with no path: the folders are "flattened."
An example: suppose the zip file contains entries /directory1/file1.txt and
/directory2/file2.txt. With FlattenFoldersOnExtract set to false,
the files created will be \directory1\file1.txt and \directory2\file2.txt.
With the property set to true, the files created are file1.txt and file2.txt.
FullScan
Indicates whether to perform a full scan of the zip file when reading it.
public bool FullScan { get; set; }
Property Value
Examples
This example shows how to read a zip file using the full scan approach, and then save it, thereby producing a corrected zip file.
using (var zip = new ZipFile())
{
zip.FullScan = true;
zip.Initialize(zipFileName);
zip.Save(newName);
}
Using zip As New ZipFile
zip.FullScan = True
zip.Initialize(zipFileName)
zip.Save(newName)
End Using
Remarks
You almost never want to use this property.
When reading a zip file, if this flag is true (True in
VB), the entire zip archive will be scanned and searched for entries.
For large archives, this can take a very, long time. The much more
efficient default behavior is to read the zip directory, which is
stored at the end of the zip file. But, in some cases the directory is
corrupted and you need to perform a full scan of the zip file to
determine the contents of the zip file. This property lets you do
that, when necessary.
This flag is effective only when calling Initialize(string). Normally you would read a ZipFile with the
static ZipFile.Read
method. But you can't set the FullScan property on the
ZipFile instance when you use a static factory method like
ZipFile.Read.
IgnoreDuplicateFiles
Indicates whether to ignore duplicate files (report only the first entry) when loading a zipfile.
public bool IgnoreDuplicateFiles { get; set; }
Property Value
Remarks
The default value is false, which will try to make all files
available (duplicates will have a "copy" suffix appended to their name).
Setting this to true prior to using Initialize to read a
zipfile will prevent this and instead just ignore the duplicates.
Info
Provides a human-readable string with information about the ZipFile.
public string Info { get; }
Property Value
Remarks
The information string contains 10 lines or so, about each ZipEntry, describing whether encryption is in use, the compressed and uncompressed length of the entry, the offset of the entry, and so on. As a result the information string can be very long for zip files that contain many entries.
This information is mostly useful for diagnostic purposes.
InputUsesZip64
Indicates whether the most recent Read() operation read a zip file that uses
ZIP64 extensions.
public bool? InputUsesZip64 { get; }
Property Value
- bool?
Remarks
This property will return null (Nothing in VB) if you've added an entry after reading the zip file.
this[int]
This is an integer indexer into the Zip archive.
public ZipEntry this[int ix] { get; }
Parameters
ixint
Property Value
- ZipEntry
The
ZipEntrywithin the Zip archive at the specified index. If the entry does not exist in the archive, this indexer throws.
Remarks
This property is read-only.
Internally, the ZipEntry instances that belong to the
ZipFile are stored in a Dictionary. When you use this
indexer the first time, it creates a read-only
List<ZipEntry> from the Dictionary.Values Collection.
If at any time you modify the set of entries in the ZipFile,
either by adding an entry, removing an entry, or renaming an
entry, a new List will be created, and the numeric indexes for the
remaining entries may be different.
This means you cannot rename any ZipEntry from inside an enumeration of the zip file.
The index value.this[string]
This is a name-based indexer into the Zip archive.
public ZipEntry this[string fileName] { get; }
Parameters
fileNamestringThe name of the file, including any directory path, to retrieve from the zip. The filename match is not case-sensitive by default; you can use the CaseSensitiveRetrieval property to change this behavior. The pathname can use forward-slashes or backward slashes.
Property Value
- ZipEntry
The
ZipEntrywithin the Zip archive, given by the specified filename. If the named entry does not exist in the archive, this indexer returnsnull(Nothingin VB).
Examples
This example extracts only the entries in a zip file that are .txt files.
using (ZipFile zip = ZipFile.Read("PackedDocuments.zip"))
{
foreach (string s1 in zip.EntryFilenames)
{
if (s1.EndsWith(".txt"))
zip[s1].Extract("textfiles");
}
}
Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip")
Dim s1 As String
For Each s1 In zip.EntryFilenames
If s1.EndsWith(".txt") Then
zip(s1).Extract("textfiles")
End If
Next
End Using
Remarks
This property is read-only.
The CaseSensitiveRetrieval property on the ZipFile
determines whether retrieval via this indexer is done via case-sensitive
comparisons. By default, retrieval is not case sensitive. This makes
sense on Windows, in which filesystems are not case sensitive.
Regardless of case-sensitivity, it is not always the case that
this[value].FileName == value. In other words, the FileName
property of the ZipEntry retrieved with this indexer, may or may
not be equal to the index value.
This is because DotNetZip performs a normalization of filenames passed to
this indexer, before attempting to retrieve the item. That normalization
includes: removal of a volume letter and colon, swapping backward slashes
for forward slashes. So, zip["dir1\\entry1.txt"].FileName ==
"dir1/entry.txt".
Directory entries in the zip file may be retrieved via this indexer only with names that have a trailing slash. DotNetZip automatically appends a trailing slash to the names of any directory entries added to a zip.
Exceptions
- ArgumentException
Thrown if the caller attempts to assign a non-null value to the indexer.
- See Also
LibraryVersion
Returns the version number on the DotNetZip assembly.
public static Version LibraryVersion { get; }
Property Value
Remarks
This property is exposed as a convenience. Callers could also get the version value by retrieving GetName().Version on the System.Reflection.Assembly object pointing to the DotNetZip assembly. But sometimes it is not clear which assembly is being loaded. This property makes it clear.
This static property is primarily useful for diagnostic purposes.
MaxOutputSegmentSize
The maximum size of an output segment, when saving a split Zip file.
public int MaxOutputSegmentSize { get; set; }
Property Value
Remarks
Make sure you do not read from this field if you've set the value using MaxOutputSegmentSize64
Set this to a non-zero value before calling Save() or Save(string) to specify that the ZipFile should be saved as a split archive, also sometimes called a spanned archive. Some also call them multi-file archives.
A split zip archive is saved in a set of discrete filesystem files,
rather than in a single file. This is handy when transmitting the
archive in email or some other mechanism that has a limit to the size of
each file. The first file in a split archive will be named
basename.z01, the second will be named basename.z02, and
so on. The final file is named basename.zip. According to the zip
specification from PKWare, the minimum value is 65536, for a 64k segment
size. The maximum number of segments allows in a split archive is 99.
The value of this property determines the maximum size of a split
segment when writing a split archive. For example, suppose you have a
ZipFile that would save to a single file of 200k. If you set the
MaxOutputSegmentSize to 65536 before calling Save(), you
will get four distinct output files. On the other hand if you set this
property to 256k, then you will get a single-file archive for that
ZipFile.
The size of each split output file will be as large as possible, up to the maximum size set here. The zip specification requires that some data fields in a zip archive may not span a split boundary, and an output segment may be smaller than the maximum if necessary to avoid that problem. Also, obviously the final segment of the archive may be smaller than the maximum segment size. Segments will never be larger than the value set with this property.
You can save a split Zip file only when saving to a regular filesystem file. It's not possible to save a split zip file as a self-extracting archive, nor is it possible to save a split zip file to a stream. When saving to a SFX or to a Stream, this property is ignored.
About interoperability: Split or spanned zip files produced by DotNetZip can be read by WinZip or PKZip, and vice-versa. Segmented zip files may not be readable by other tools, if those other tools don't support zip spanning or splitting. When in doubt, test. I don't believe Windows Explorer can extract a split archive.
This property has no effect when reading a split archive. You can read a split archive in the normal way with DotNetZip.
When saving a zip file, if you want a regular zip file rather than a split zip file, don't set this property, or set it to Zero.
If you read a split archive, with Read(string) and
then subsequently call ZipFile.Save(), unless you set this
property before calling Save(), you will get a normal,
single-file archive.
- See Also
MaxOutputSegmentSize64
The maximum size of an output segment, when saving a split Zip file.
public long MaxOutputSegmentSize64 { get; set; }
Property Value
Remarks
If you set this value, make sure you do not accidently use MaxOutputSegmentSize in your code
Set this to a non-zero value before calling Save() or Save(string) to specify that the ZipFile should be saved as a split archive, also sometimes called a spanned archive. Some also call them multi-file archives.
A split zip archive is saved in a set of discrete filesystem files,
rather than in a single file. This is handy when transmitting the
archive in email or some other mechanism that has a limit to the size of
each file. The first file in a split archive will be named
basename.z01, the second will be named basename.z02, and
so on. The final file is named basename.zip. According to the zip
specification from PKWare, the minimum value is 65536, for a 64k segment
size. The maximum number of segments allows in a split archive is 99.
The value of this property determines the maximum size of a split
segment when writing a split archive. For example, suppose you have a
ZipFile that would save to a single file of 200k. If you set the
MaxOutputSegmentSize to 65536 before calling Save(), you
will get four distinct output files. On the other hand if you set this
property to 256k, then you will get a single-file archive for that
ZipFile.
The size of each split output file will be as large as possible, up to the maximum size set here. The zip specification requires that some data fields in a zip archive may not span a split boundary, and an output segment may be smaller than the maximum if necessary to avoid that problem. Also, obviously the final segment of the archive may be smaller than the maximum segment size. Segments will never be larger than the value set with this property.
You can save a split Zip file only when saving to a regular filesystem file. It's not possible to save a split zip file as a self-extracting archive, nor is it possible to save a split zip file to a stream. When saving to a SFX or to a Stream, this property is ignored.
About interoperability: Split or spanned zip files produced by DotNetZip can be read by WinZip or PKZip, and vice-versa. Segmented zip files may not be readable by other tools, if those other tools don't support zip spanning or splitting. When in doubt, test. I don't believe Windows Explorer can extract a split archive.
This property has no effect when reading a split archive. You can read a split archive in the normal way with DotNetZip.
When saving a zip file, if you want a regular zip file rather than a split zip file, don't set this property, or set it to Zero.
If you read a split archive, with Read(string) and
then subsequently call ZipFile.Save(), unless you set this
property before calling Save(), you will get a normal,
single-file archive.
- See Also
Name
The name of the ZipFile, on disk.
public string Name { get; set; }
Property Value
Remarks
When the ZipFile instance was created by reading an archive using
one of the ZipFile.Read methods, this property represents the name
of the zip file that was read. When the ZipFile instance was
created by using the no-argument constructor, this value is null
(Nothing in VB).
If you use the no-argument constructor, and you then explicitly set this
property, when you call Save(), this name will
specify the name of the zip file created. Doing so is equivalent to
calling Save(string). When instantiating a
ZipFile by reading from a stream or byte array, the Name
property remains null. When saving to a stream, the Name
property is implicitly set to null.
NumberOfSegmentsForMostRecentSave
Returns the number of segments used in the most recent Save() operation.
public int NumberOfSegmentsForMostRecentSave { get; }
Property Value
Remarks
This is normally zero, unless you have set the MaxOutputSegmentSize property. If you have set MaxOutputSegmentSize, and then you save a file, after the call to Save() completes, you can read this value to learn the number of segments that were created.
If you call Save("Archive.zip"), and it creates 5 segments, then you will have filesystem files named Archive.z01, Archive.z02, Archive.z03, Archive.z04, and Archive.zip, and the value of this property will be 5.
- See Also
OutputUsedZip64
Indicates whether the most recent Save() operation used ZIP64 extensions.
public bool? OutputUsedZip64 { get; }
Property Value
- bool?
Remarks
The use of ZIP64 extensions within an archive is not always necessary, and
for interoperability concerns, it may be desired to NOT use ZIP64 if
possible. The UseZip64WhenSaving property can be
set to use ZIP64 extensions only when necessary. In those cases,
Sometimes applications want to know whether a Save() actually used ZIP64
extensions. Applications can query this read-only property to learn
whether ZIP64 has been used in a just-saved ZipFile.
The value is null (or Nothing in VB) if the archive has not
been saved.
Non-null values (HasValue is true) indicate whether ZIP64
extensions were used during the most recent Save() operation. The
ZIP64 extensions may have been used as required by any particular entry
because of its uncompressed or compressed size, or because the archive is
larger than 4294967295 bytes, or because there are more than 65534 entries
in the archive, or because the UseZip64WhenSaving property was set
to Always, or because the
UseZip64WhenSaving property was set to AsNecessary and the output stream was not seekable.
The value of this property does not indicate the reason the ZIP64
extensions were used.
- See Also
ParallelDeflateMaxBufferPairs
The maximum number of buffer pairs to use when performing parallel compression.
public int ParallelDeflateMaxBufferPairs { get; set; }
Property Value
Remarks
This property sets an upper limit on the number of memory buffer pairs to create when performing parallel compression. The implementation of the parallel compression stream allocates multiple buffers to facilitate parallel compression. As each buffer fills up, the stream uses ThreadPool.QueueUserWorkItem() to compress those buffers in a background threadpool thread. After a buffer is compressed, it is re-ordered and written to the output stream.
A higher number of buffer pairs enables a higher degree of parallelism, which tends to increase the speed of compression on multi-cpu computers. On the other hand, a higher number of buffer pairs also implies a larger memory consumption, more active worker threads, and a higher cpu utilization for any compression. This property enables the application to limit its memory consumption and CPU utilization behavior depending on requirements.
For each compression "task" that occurs in parallel, there are 2 buffers allocated: one for input and one for output. This property sets a limit for the number of pairs. The total amount of storage space allocated for buffering will then be (N*S*2), where N is the number of buffer pairs, S is the size of each buffer (BufferSize). By default, DotNetZip allocates 4 buffer pairs per CPU core, so if your machine has 4 cores, and you retain the default buffer size of 128k, then the ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer memory in total, or 4mb, in blocks of 128kb. If you then set this property to 8, then the number will be 8 * 2 * 128kb of buffer memory, or 2mb.
CPU utilization will also go up with additional buffers, because a larger number of buffer pairs allows a larger number of background threads to compress in parallel. If you find that parallel compression is consuming too much memory or CPU, you can adjust this value downward.
The default value is 16. Different values may deliver better or worse results, depending on your priorities and the dynamic performance characteristics of your storage and compute resources.
This property is not the number of buffer pairs to use; it is an upper limit. An illustration: Suppose you have an application that uses the default value of this property (which is 16), and it runs on a machine with 2 CPU cores. In that case, DotNetZip will allocate 4 buffer pairs per CPU core, for a total of 8 pairs. The upper limit specified by this property has no effect.
The application can set this value at any time
before calling ZipFile.Save().
- See Also
ParallelDeflateThreshold
The size threshold for an entry, above which a parallel deflate is used.
public long ParallelDeflateThreshold { get; set; }
Property Value
Remarks
DotNetZip will use multiple threads to compress any ZipEntry, if the entry is larger than the given size. Zero means "always use parallel deflate", while -1 means "never use parallel deflate". The default value for this property is 512k. Aside from the special values of 0 and 1, the minimum value is 65536.
If the entry size cannot be known before compression, as with a read-forward stream, then Parallel deflate will never be performed, unless the value of this property is zero.
A parallel deflate operations will speed up the compression of large files, on computers with multiple CPUs or multiple CPU cores. For files above 1mb, on a dual core or dual-cpu (2p) machine, the time required to compress the file can be 70% of the single-threaded deflate. For very large files on 4p machines the compression can be done in 30% of the normal time. The downside is that parallel deflate consumes extra memory during the deflate, and the deflation is not as effective.
Parallel deflate tends to yield slightly less compression when compared to as single-threaded deflate; this is because the original data stream is split into multiple independent buffers, each of which is compressed in parallel. But because they are treated independently, there is no opportunity to share compression dictionaries. For that reason, a deflated stream may be slightly larger when compressed using parallel deflate, as compared to a traditional single-threaded deflate. Sometimes the increase over the normal deflate is as much as 5% of the total compressed size. For larger files it can be as small as 0.1%.
Multi-threaded compression does not give as much an advantage when using Encryption. This is primarily because encryption tends to slow down the entire pipeline. Also, multi-threaded compression gives less of an advantage when using lower compression levels, for example BestSpeed. You may have to perform some tests to determine the best approach for your situation.
- See Also
Password
Sets the password to be used on the ZipFile instance.
public string Password { set; }
Property Value
Examples
This example creates a zip file, using password protection for the entries, and then extracts the entries from the zip file. When creating the zip file, the Readme.txt file is not protected with a password, but the other two are password-protected as they are saved. During extraction, each file is extracted with the appropriate password.
// create a file with encryption
using (ZipFile zip = new ZipFile())
{
zip.AddFile("ReadMe.txt");
zip.Password= "!Secret1";
zip.AddFile("MapToTheSite-7440-N49th.png");
zip.AddFile("2008-Regional-Sales-Report.pdf");
zip.Save("EncryptedArchive.zip");
}
// extract entries that use encryption
using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
{
zip.Password= "!Secret1";
zip.ExtractAll("extractDir");
}
Using zip As New ZipFile
zip.AddFile("ReadMe.txt")
zip.Password = "123456!"
zip.AddFile("MapToTheSite-7440-N49th.png")
zip.Password= "!Secret1";
zip.AddFile("2008-Regional-Sales-Report.pdf")
zip.Save("EncryptedArchive.zip")
End Using
' extract entries that use encryption
Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
zip.Password= "!Secret1"
zip.ExtractAll("extractDir")
End Using
Remarks
When writing a zip archive, this password is applied to the entries, not
to the zip archive itself. It applies to any ZipEntry subsequently
added to the ZipFile, using one of the AddFile,
AddDirectory, AddEntry, or AddItem methods, etc.
When reading a zip archive, this property applies to any entry
subsequently extracted from the ZipFile using one of the Extract
methods on the ZipFile class.
When writing a zip archive, keep this in mind: though the password is set on the ZipFile object, according to the Zip spec, the "directory" of the archive - in other words the list of entries or files contained in the archive - is not encrypted with the password, or protected in any way. If you set the Password property, the password actually applies to individual entries that are added to the archive, subsequent to the setting of this property. The list of filenames in the archive that is eventually created will appear in clear text, but the contents of the individual files are encrypted. This is how Zip encryption works.
One simple way around this limitation is to simply double-wrap sensitive filenames: Store the files in a zip file, and then store that zip file within a second, "outer" zip file. If you apply a password to the outer zip file, then readers will be able to see that the outer zip file contains an inner zip file. But readers will not be able to read the directory or file list of the inner zip file.
If you set the password on the ZipFile, and then add a set of files
to the archive, then each entry is encrypted with that password. You may
also want to change the password between adding different entries. If you
set the password, add an entry, then set the password to null
(Nothing in VB), and add another entry, the first entry is
encrypted and the second is not. If you call AddFile(), then set
the Password property, then call ZipFile.Save, the file
added will not be password-protected, and no warning will be generated.
When setting the Password, you may also want to explicitly set the Encryption property, to specify how to encrypt the entries added
to the ZipFile. If you set the Password to a non-null value and do not
set Encryption, then PKZip 2.0 ("Weak") encryption is used.
This encryption is relatively weak but is very interoperable. If you set
the password to a null value (Nothing in VB), Encryption is
reset to None.
All of the preceding applies to writing zip archives, in other words when
you use one of the Save methods. To use this property when reading or an
existing ZipFile, do the following: set the Password property on the
ZipFile, then call one of the Extract() overloads on the ZipEntry. In this case, the entry is extracted using the
Password that is specified on the ZipFile instance. If you
have not set the Password property, then the password is
null, and the entry is extracted with no password.
If you set the Password property on the ZipFile, then call
Extract() an entry that has not been encrypted with a password, the
password is not used for that entry, and the ZipEntry is extracted
as normal. In other words, the password is used only if necessary.
The ZipEntry class also has a Password property. It takes precedence
over this property on the ZipFile. Typically, you would use the
per-entry Password when most entries in the zip archive use one password,
and a few entries use a different password. If all entries in the zip
file use the same password, then it is simpler to just set this property
on the ZipFile itself, whether creating a zip archive or extracting
a zip archive.
- See Also
ProvisionalAlternateEncoding
The text encoding to use when writing new entries to the ZipFile,
for those entries that cannot be encoded with the default (IBM437)
encoding; or, the text encoding that was used when reading the entries
from the ZipFile.
[Obsolete("use AlternateEncoding instead.")]
public Encoding ProvisionalAlternateEncoding { get; set; }
Property Value
Examples
This example shows how to read a zip file using the Big-5 Chinese code page
(950), and extract each entry in the zip file. For this code to work as
desired, the Zipfile must have been created using the big5 code page
(CP950). This is typical, for example, when using WinRar on a machine with
CP950 set as the default code page. In that case, the names of entries
within the Zip archive will be stored in that code page, and reading the zip
archive must be done using that code page. If the application did not use
the correct code page in ZipFile.Read(), then names of entries within the
zip archive would not be correctly retrieved.
using (var zip = ZipFile.Read(zipFileName, System.Text.Encoding.GetEncoding("big5")))
{
// retrieve and extract an entry using a name encoded with CP950
zip[MyDesiredEntry].Extract("unpack");
}
Using zip As ZipFile = ZipFile.Read(ZipToExtract, System.Text.Encoding.GetEncoding("big5"))
' retrieve and extract an entry using a name encoded with CP950
zip(MyDesiredEntry).Extract("unpack")
End Using
Remarks
In its zip specification, PKWare describes two options for encoding filenames and comments: using IBM437 or UTF-8. But, some archiving tools or libraries do not follow the specification, and instead encode characters using the system default code page. For example, WinRAR when run on a machine in Shanghai may encode filenames with the Big-5 Chinese (950) code page. This behavior is contrary to the Zip specification, but it occurs anyway.
When using DotNetZip to write zip archives that will be read by one of
these other archivers, set this property to specify the code page to use
when encoding the FileName and Comment for each ZipEntry in the zip file, for
values that cannot be encoded with the default codepage for zip files,
IBM437. This is why this property is "provisional". In all cases, IBM437
is used where possible, in other words, where no loss of data would
result. It is possible, therefore, to have a given entry with a
Comment encoded in IBM437 and a FileName encoded with the
specified "provisional" codepage.
Be aware that a zip file created after you've explicitly set the ProvisionalAlternateEncoding property to a value other than IBM437 may not be compliant to the PKWare specification, and may not be readable by compliant archivers. On the other hand, many (most?) archivers are non-compliant and can read zip files created in arbitrary code pages. The trick is to use or specify the proper codepage when reading the zip.
When creating a zip archive using this library, it is possible to change
the value of ProvisionalAlternateEncoding between each
entry you add, and between adding entries and the call to
Save(). Don't do this. It will likely result in a zipfile that is
not readable. For best interoperability, either leave ProvisionalAlternateEncoding alone, or specify it only once,
before adding any entries to the ZipFile instance. There is one
exception to this recommendation, described later.
When using an arbitrary, non-UTF8 code page for encoding, there is no standard way for the creator application - whether DotNetZip, WinZip, WinRar, or something else - to formally specify in the zip file which codepage has been used for the entries. As a result, readers of zip files are not able to inspect the zip file and determine the codepage that was used for the entries contained within it. It is left to the application or user to determine the necessary codepage when reading zip files encoded this way. In other words, if you explicitly specify the codepage when you create the zipfile, you must explicitly specify the same codepage when reading the zipfile.
The way you specify the code page to use when reading a zip file varies depending on the tool or library you use to read the zip. In DotNetZip, you use a ZipFile.Read() method that accepts an encoding parameter. It isn't possible with Windows Explorer, as far as I know, to specify an explicit codepage to use when reading a zip. If you use an incorrect codepage when reading a zipfile, you will get entries with filenames that are incorrect, and the incorrect filenames may even contain characters that are not legal for use within filenames in Windows. Extracting entries with illegal characters in the filenames will lead to exceptions. It's too bad, but this is just the way things are with code pages in zip files. Caveat Emptor.
Example: Suppose you create a zipfile that contains entries with filenames that have Danish characters. If you use ProvisionalAlternateEncoding equal to "iso-8859-1" (cp 28591), the filenames will be correctly encoded in the zip. But, to read that zipfile correctly, you have to specify the same codepage at the time you read it. If try to read that zip file with Windows Explorer or another application that is not flexible with respect to the codepage used to decode filenames in zipfiles, you will get a filename like "Infďż˝.txt".
When using DotNetZip to read a zip archive, and the zip archive uses an
arbitrary code page, you must specify the encoding to use before or when
the Zipfile is READ. This means you must use a ZipFile.Read()
method that allows you to specify a System.Text.Encoding parameter. Setting
the ProvisionalAlternateEncoding property after your application has read in
the zip archive will not affect the entry names of entries that have already
been read in.
And now, the exception to the rule described above. One strategy for
specifying the code page for a given zip file is to describe the code page
in a human-readable form in the Zip comment. For example, the comment may
read "Entries in this archive are encoded in the Big5 code page". For
maximum interoperability, the zip comment in this case should be encoded
in the default, IBM437 code page. In this case, the zip comment is
encoded using a different page than the filenames. To do this, Specify
ProvisionalAlternateEncoding to your desired region-specific code
page, once before adding any entries, and then reset
ProvisionalAlternateEncoding to IBM437 before setting the Comment property and calling Save().
- See Also
RequiresZip64
Indicates whether the archive requires ZIP64 extensions.
public bool? RequiresZip64 { get; }
Property Value
- bool?
Remarks
This property is null (or Nothing in VB) if the archive has
not been saved, and there are fewer than 65334 ZipEntry items
contained in the archive.
The Value is true if any of the following four conditions holds:
the uncompressed size of any entry is larger than 0xFFFFFFFF; the
compressed size of any entry is larger than 0xFFFFFFFF; the relative
offset of any entry within the zip archive is larger than 0xFFFFFFFF; or
there are more than 65534 entries in the archive. (0xFFFFFFFF =
4,294,967,295). The result may not be known until a Save() is attempted
on the zip archive. The Value of this Nullable
property may be set only AFTER one of the Save() methods has been called.
If none of the four conditions holds, and the archive has been saved, then
the Value is false.
A Value of false does not indicate that the zip archive, as saved,
does not use ZIP64. It merely indicates that ZIP64 is not required. An
archive may use ZIP64 even when not required if the UseZip64WhenSaving property is set to Always, or if the UseZip64WhenSaving property is set to AsNecessary and the output stream was not
seekable. Use the OutputUsedZip64 property to determine if
the most recent Save() method resulted in an archive that utilized
the ZIP64 extensions.
- See Also
SetCompression
A callback that allows the application to specify the compression level to use for entries subsequently added to the zip archive.
public SetCompressionCallback SetCompression { get; set; }
Property Value
Remarks
With this callback, the DotNetZip library allows the application to
determine whether compression will be used, at the time of the
Save. This may be useful if the application wants to favor
speed over size, and wants to defer the decision until the time of
Save.
Typically applications set the CompressionLevel property on
the ZipFile or on each ZipEntry to determine the level of
compression used. This is done at the time the entry is added to the
ZipFile. Setting the property to
CompressionLevel.None means no compression will be used.
This callback allows the application to defer the decision on the
CompressionLevel to use, until the time of the call to
ZipFile.Save(). The callback is invoked once per ZipEntry,
at the time the data for the entry is being written out as part of a
Save() operation. The application can use whatever criteria it
likes in determining the level to return. For example, an application may
wish that no .mp3 files should be compressed, because they are already
compressed and the extra compression is not worth the CPU time incurred,
and so can return None for all .mp3 entries.
The library determines whether compression will be attempted for an entry
this way: If the entry is a zero length file, or a directory, no
compression is used. Otherwise, if this callback is set, it is invoked
and the CompressionLevel is set to the return value. If this
callback has not been set, then the previously set value for
CompressionLevel is used.
SortEntriesBeforeSaving
Whether to sort the ZipEntries before saving the file.
public bool SortEntriesBeforeSaving { get; set; }
Property Value
Examples
using (var zip = new ZipFile())
{
zip.AddFiles(filesToAdd);
zip.SortEntriesBeforeSaving = true;
zip.Save(name);
}
Using zip As New ZipFile
zip.AddFiles(filesToAdd)
zip.SortEntriesBeforeSaving = True
zip.Save(name)
End Using
Remarks
The default is false. If you have a large number of zip entries, the sort alone can consume significant time.
StatusMessageTextWriter
Gets or sets the TextWriter to which status messages are delivered
for the instance.
public TextWriter StatusMessageTextWriter { get; set; }
Property Value
Examples
In this example, a console application instantiates a ZipFile, then
sets the StatusMessageTextWriter to Console.Out. At that
point, all verbose status messages for that ZipFile are sent to the
console.
using (ZipFile zip= ZipFile.Read(FilePath))
{
zip.StatusMessageTextWriter= System.Console.Out;
// messages are sent to the console during extraction
zip.ExtractAll();
}
Using zip As ZipFile = ZipFile.Read(FilePath)
zip.StatusMessageTextWriter= System.Console.Out
'Status Messages will be sent to the console during extraction
zip.ExtractAll()
End Using
In this example, a Windows Forms application instantiates a
ZipFile, then sets the StatusMessageTextWriter to a
StringWriter. At that point, all verbose status messages for that
ZipFile are sent to the StringWriter.
var sw = new System.IO.StringWriter();
using (ZipFile zip= ZipFile.Read(FilePath))
{
zip.StatusMessageTextWriter= sw;
zip.ExtractAll();
}
Console.WriteLine("{0}", sw.ToString());
Dim sw as New System.IO.StringWriter
Using zip As ZipFile = ZipFile.Read(FilePath)
zip.StatusMessageTextWriter= sw
zip.ExtractAll()
End Using
'Status Messages are now available in sw
Remarks
If the TextWriter is set to a non-null value, then verbose output is sent
to the TextWriter during Add, Read, Save and
Extract operations. Typically, console applications might use
Console.Out and graphical or headless applications might use a
System.IO.StringWriter. The output of this is suitable for viewing
by humans.
Strategy
The compression strategy to use for all entries.
public CompressionStrategy Strategy { get; set; }
Property Value
Remarks
Set the Strategy used by the ZLIB-compatible compressor, when compressing entries using the DEFLATE method. Different compression strategies work better on different sorts of data. The strategy parameter can affect the compression ratio and the speed of compression but not the correctness of the compresssion. For more information see CompressionStrategy.
TempFileFolder
Gets or sets the name for the folder to store the temporary file this library writes when saving a zip archive.
public string TempFileFolder { get; set; }
Property Value
Remarks
This library will create a temporary file when saving a Zip archive to a
file. This file is written when calling one of the Save() methods
that does not save to a stream, or one of the SaveSelfExtractor()
methods.
By default, the library will create the temporary file in the directory specified for the file itself, via the Name property or via the Save(string) method.
Setting this property allows applications to override this default
behavior, so that the library will create the temporary file in the
specified folder. For example, to have the library create the temporary
file in the current working directory, regardless where the ZipFile
is saved, specfy ".". To revert to the default behavior, set this
property to null (Nothing in VB).
When setting the property to a non-null value, the folder specified must
exist; if it does not an exception is thrown. The application should have
write and delete permissions on the folder. The permissions are not
explicitly checked ahead of time; if the application does not have the
appropriate rights, an exception will be thrown at the time Save()
is called.
There is no temporary file created when reading a zip archive. When
saving to a Stream, there is no temporary file created. For example, if
the application is an ASP.NET application and calls Save()
specifying the Response.OutputStream as the output stream, there is
no temporary file created.
Exceptions
- FileNotFoundException
Thrown when setting the property if the directory does not exist.
UseUnicodeAsNecessary
Indicates whether to encode entry filenames and entry comments using Unicode (UTF-8).
[Obsolete("Beginning with v1.9.1.6 of DotNetZip, this property is obsolete. It will be removed in a future version of the library. Your applications should use AlternateEncoding and AlternateEncodingUsage instead.")]
public bool UseUnicodeAsNecessary { get; set; }
Property Value
Remarks
The PKWare zip specification provides for encoding file names and file comments in either the IBM437 code page, or in UTF-8. This flag selects the encoding according to that specification. By default, this flag is false, and filenames and comments are encoded into the zip file in the IBM437 codepage. Setting this flag to true will specify that filenames and comments that cannot be encoded with IBM437 will be encoded with UTF-8.
Zip files created with strict adherence to the PKWare specification with respect to UTF-8 encoding can contain entries with filenames containing any combination of Unicode characters, including the full range of characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other alphabets. However, because at this time, the UTF-8 portion of the PKWare specification is not broadly supported by other zip libraries and utilities, such zip files may not be readable by your favorite zip tool or archiver. In other words, interoperability will decrease if you set this flag to true.
In particular, Zip files created with strict adherence to the PKWare specification with respect to UTF-8 encoding will not work well with Explorer in Windows XP or Windows Vista, because Windows compressed folders, as far as I know, do not support UTF-8 in zip files. Vista can read the zip files, but shows the filenames incorrectly. Unpacking from Windows Vista Explorer will result in filenames that have rubbish characters in place of the high-order UTF-8 bytes.
Also, zip files that use UTF-8 encoding will not work well with Java applications that use the java.util.zip classes, as of v5.0 of the Java runtime. The Java runtime does not correctly implement the PKWare specification in this regard.
As a result, we have the unfortunate situation that "correct" behavior by the DotNetZip library with regard to Unicode encoding of filenames during zip creation will result in zip files that are readable by strictly compliant and current tools (for example the most recent release of the commercial WinZip tool); but these zip files will not be readable by various other tools or libraries, including Windows Explorer.
The DotNetZip library can read and write zip files with UTF8-encoded entries, according to the PKware spec. If you use DotNetZip for both creating and reading the zip file, and you use UTF-8, there will be no loss of information in the filenames. For example, using a self-extractor created by this library will allow you to unpack files correctly with no loss of information in the filenames.
If you do not set this flag, it will remain false. If this flag is false,
your ZipFile will encode all filenames and comments using the
IBM437 codepage. This can cause "loss of information" on some filenames,
but the resulting zipfile will be more interoperable with other
utilities. As an example of the loss of information, diacritics can be
lost. The o-tilde character will be down-coded to plain o. The c with a
cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c.
Likewise, the O-stroke character (Unicode 248), used in Danish and
Norwegian, will be down-coded to plain o. Chinese characters cannot be
represented in codepage IBM437; when using the default encoding, Chinese
characters in filenames will be represented as ?. These are all examples
of "information loss".
The loss of information associated to the use of the IBM437 encoding is
inconvenient, and can also lead to runtime errors. For example, using
IBM437, any sequence of 4 Chinese characters will be encoded as ????. If
your application creates a ZipFile, then adds two files, each with
names of four Chinese characters each, this will result in a duplicate
filename exception. In the case where you add a single file with a name
containing four Chinese characters, calling Extract() on the entry that
has question marks in the filename will result in an exception, because
the question mark is not legal for use within filenames on Windows. These
are just a few examples of the problems associated to loss of information.
This flag is independent of the encoding of the content within the entries in the zip file. Think of the zip file as a container - it supports an encoding. Within the container are other "containers" - the file entries themselves. The encoding within those entries is independent of the encoding of the zip archive container for those entries.
Rather than specify the encoding in a binary fashion using this flag, an application can specify an arbitrary encoding via the ProvisionalAlternateEncoding property. Setting the encoding explicitly when creating zip archives will result in non-compliant zip files that, curiously, are fairly interoperable. The challenge is, the PKWare specification does not provide for a way to specify that an entry in a zip archive uses a code page that is neither IBM437 nor UTF-8. Therefore if you set the encoding explicitly when creating a zip archive, you must take care upon reading the zip archive to use the same code page. If you get it wrong, the behavior is undefined and may result in incorrect filenames, exceptions, stomach upset, hair loss, and acne.
- See Also
UseZip64WhenSaving
Specify whether to use ZIP64 extensions when saving a zip archive.
public Zip64Option UseZip64WhenSaving { get; set; }
Property Value
Remarks
When creating a zip file, the default value for the property is Never. AsNecessary is safest, in the sense that you will not get an Exception if a pre-ZIP64 limit is exceeded.
You may set the property at any time before calling Save().
When reading a zip file via the Zipfile.Read() method, DotNetZip
will properly read ZIP64-endowed zip archives, regardless of the value of
this property. DotNetZip will always read ZIP64 archives. This property
governs only whether DotNetZip will write them. Therefore, when updating
archives, be careful about setting this property after reading an archive
that may use ZIP64 extensions.
An interesting question is, if you have set this property to
AsNecessary, and then successfully saved, does the resulting
archive use ZIP64 extensions or not? To learn this, check the OutputUsedZip64 property, after calling Save().
Have you thought about donating?
- See Also
ZipErrorAction
The action the library should take when an error is encountered while opening or reading files as they are saved into a zip archive.
public ZipErrorAction ZipErrorAction { get; set; }
Property Value
Examples
This example shows how to tell DotNetZip to skip any files for which an error is generated during the Save().
Public Sub SaveZipFile()
Dim SourceFolder As String = "fodder"
Dim DestFile As String = "eHandler.zip"
Dim sw as New StringWriter
Using zipArchive As ZipFile = New ZipFile
' Tell DotNetZip to skip any files for which it encounters an error
zipArchive.ZipErrorAction = ZipErrorAction.Skip
zipArchive.StatusMessageTextWriter = sw
zipArchive.AddDirectory(SourceFolder)
zipArchive.Save(DestFile)
End Using
' examine sw here to see any messages
End Sub
Remarks
Errors can occur as a file is being saved to the zip archive. For example, the File.Open may fail, or a File.Read may fail, because of lock conflicts or other reasons.
The first problem might occur after having called AddDirectory() on a directory that contains a Clipper .dbf file; the file is locked by Clipper and cannot be opened for read by another process. An example of the second problem might occur when trying to zip a .pst file that is in use by Microsoft Outlook. Outlook locks a range on the file, which allows other processes to open the file, but not read it in its entirety.
This property tells DotNetZip what you would like to do in the case of
these errors. The primary options are: ZipErrorAction.Throw to
throw an exception (this is the default behavior if you don't set this
property); ZipErrorAction.Skip to Skip the file for which there
was an error and continue saving; ZipErrorAction.Retry to Retry
the entry that caused the problem; or
ZipErrorAction.InvokeErrorEvent to invoke an event handler.
This property is implicitly set to ZipErrorAction.InvokeErrorEvent
if you add a handler to the ZipError event. If you set
this property to something other than
ZipErrorAction.InvokeErrorEvent, then the ZipError
event is implicitly cleared. What it means is you can set one or the
other (or neither), depending on what you want, but you never need to set
both.
As with some other properties on the ZipFile class, like Password, Encryption, and CompressionLevel, setting this property on a ZipFile
instance will cause the specified ZipErrorAction to be used on all
ZipEntry items that are subsequently added to the
ZipFile instance. If you set this property after you have added
items to the ZipFile, but before you have called Save(),
those items will not use the specified error handling action.
If you want to handle any errors that occur with any entry in the zip file in the same way, then set this property once, before adding any entries to the zip archive.
If you set this property to ZipErrorAction.Skip and you'd like to
learn which files may have been skipped after a Save(), you can
set the StatusMessageTextWriter on the ZipFile before
calling Save(). A message will be emitted into that writer for
each skipped file, if any.
- See Also
Methods
AddDirectory(string)
Adds the contents of a filesystem directory to a Zip file archive.
public ZipEntry AddDirectory(string directoryName)
Parameters
directoryNamestringThe name of the directory to add.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
The name of the directory may be a relative path or a fully-qualified path. Any files within the named directory are added to the archive. Any subdirectories within the named directory are also added to the archive, recursively.
Top-level entries in the named directory will appear as top-level entries in the zip archive. Entries in subdirectories in the named directory will result in entries in subdirectories in the zip archive.
If you want the entries to appear in a containing directory in the zip archive itself, then you should call the AddDirectory() overload that allows you to explicitly specify a directory path for use in the archive.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to each
ZipEntry added.
- See Also
AddDirectory(string, string)
Adds the contents of a filesystem directory to a Zip file archive, overriding the path to be used for entries in the archive.
public ZipEntry AddDirectory(string directoryName, string directoryPathInArchive)
Parameters
directoryNamestringThe name of the directory to add.
directoryPathInArchivestringSpecifies a directory path to use to override any path in the DirectoryName. This path may, or may not, correspond to a real directory in the current filesystem. If the zip is later extracted, this is the path used for the extracted file or directory. Passing
null(Nothingin VB) or the empty string ("") will insert the items at the root path within the archive.
Returns
- ZipEntry
The
ZipEntryadded.
Examples
In this code, calling the ZipUp() method with a value of "c:\reports" for the directory parameter will result in a zip file structure in which all entries are contained in a toplevel "reports" directory.
public void ZipUp(string targetZip, string directory)
{
using (var zip = new ZipFile())
{
zip.AddDirectory(directory, System.IO.Path.GetFileName(directory));
zip.Save(targetZip);
}
}
Remarks
The name of the directory may be a relative path or a fully-qualified path. The add operation is recursive, so that any files or subdirectories within the name directory are also added to the archive.
Top-level entries in the named directory will appear as top-level entries in the zip archive. Entries in subdirectories in the named directory will result in entries in subdirectories in the zip archive.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to each
ZipEntry added.
- See Also
AddDirectoryByName(string)
Creates a directory in the zip archive.
public ZipEntry AddDirectoryByName(string directoryNameInArchive)
Parameters
directoryNameInArchivestringThe name of the directory to create in the archive.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
Use this when you want to create a directory in the archive but there is no corresponding filesystem representation for that directory.
You will probably not need to do this in your code. One of the only times you will want to do this is if you want an empty directory in the zip archive. The reason: if you add a file to a zip archive that is stored within a multi-level directory, all of the directory tree is implicitly created in the zip archive.
AddEntry(ZipEntry)
Adds a ZipEntry to the zip file.
public void AddEntry(ZipEntry ze)
Parameters
Exceptions
- InvalidOperationException
Thrown if the
zealready belongs to a zip file.
AddEntry(string, OpenDelegate, CloseDelegate)
Add an entry, for which the application will provide a stream containing the entry data, on a just-in-time basis.
public ZipEntry AddEntry(string entryName, OpenDelegate opener, CloseDelegate closer)
Parameters
entryNamestringthe name of the entry to add
openerOpenDelegatethe delegate that will be invoked by ZipFile.Save() to get the readable stream for the given entry. ZipFile.Save() will call read on this stream to obtain the data for the entry. This data will then be compressed and written to the newly created zip file.
closerCloseDelegatethe delegate that will be invoked to close the stream. This may be null (Nothing in VB), in which case no call is makde to close the stream.
Returns
- ZipEntry
the ZipEntry added
Examples
This example uses anonymous methods in C# to open and close the source stream for the content for a zip entry.
using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
{
zip.AddEntry(zipEntryName,
(name) => File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ),
(name, stream) => stream.Close()
);
zip.Save(zipFileName);
}
This example uses delegates in VB.NET to open and close the the source stream for the content for a zip entry. VB 9.0 lacks support for "Sub" lambda expressions, and so the CloseDelegate must be an actual, named Sub.
Function MyStreamOpener(ByVal entryName As String) As Stream
'' This simply opens a file. You probably want to do somethinig
'' more involved here: open a stream to read from a database,
'' open a stream on an HTTP connection, and so on.
Return File.OpenRead(entryName)
End Function
Sub MyStreamCloser(entryName As String, stream As Stream)
stream.Close()
End Sub
Public Sub Run()
Dim dirToZip As String = "fodder"
Dim zipFileToCreate As String = "Archive.zip"
Dim opener As OpenDelegate = AddressOf MyStreamOpener
Dim closer As CloseDelegate = AddressOf MyStreamCloser
Dim numFilestoAdd As Int32 = 4
Using zip As ZipFile = New ZipFile
Dim i As Integer
For i = 0 To numFilesToAdd - 1
zip.AddEntry(String.Format("content-{0:000}.txt"), opener, closer)
Next i
zip.Save(zipFileToCreate)
End Using
End Sub
Remarks
In cases where the application wishes to open the stream that holds the content for the ZipEntry, on a just-in-time basis, the application can use this method. The application provides an opener delegate that will be called by the DotNetZip library to obtain a readable stream that can be read to get the bytes for the given entry. Typically, this delegate opens a stream. Optionally, the application can provide a closer delegate as well, which will be called by DotNetZip when all bytes have been read from the entry.
These delegates are called from within the scope of the call to ZipFile.Save().
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
AddEntry(string, WriteDelegate)
Add a ZipEntry for which content is written directly by the application.
public ZipEntry AddEntry(string entryName, WriteDelegate writer)
Parameters
entryNamestringthe name of the entry to add
writerWriteDelegatethe delegate which will write the entry content
Returns
- ZipEntry
the ZipEntry added
Examples
This example shows an application filling a DataSet, then saving the contents of that DataSet as XML, into a ZipEntry in a ZipFile, using an anonymous delegate in C#. The DataSet XML is never saved to a disk file.
var c1= new System.Data.SqlClient.SqlConnection(connstring1);
var da = new System.Data.SqlClient.SqlDataAdapter()
{
SelectCommand= new System.Data.SqlClient.SqlCommand(strSelect, c1)
};
DataSet ds1 = new DataSet();
da.Fill(ds1, "Invoices");
using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
{
zip.AddEntry(zipEntryName, (name,stream) => ds1.WriteXml(stream) );
zip.Save(zipFileName);
}
This example uses an anonymous method in C# as the WriteDelegate to provide
the data for the ZipEntry. The example is a bit contrived - the
AddFile() method is a simpler way to insert the contents of a file
into an entry in a zip file. On the other hand, if there is some sort of
processing or transformation of the file contents required before writing,
the application could use the WriteDelegate to do it, in this way.
using (var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ))
{
using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
{
zip.AddEntry(zipEntryName, (name,output) =>
{
byte[] buffer = new byte[BufferSize];
int n;
while ((n = input.Read(buffer, 0, buffer.Length)) != 0)
{
// could transform the data here...
output.Write(buffer, 0, n);
// could update a progress bar here
}
});
zip.Save(zipFileName);
}
}
This example uses a named delegate in VB to write data for the given
ZipEntry (VB9 does not have anonymous delegates). The example here is a bit
contrived - a simpler way to add the contents of a file to a ZipEntry is to
simply use the appropriate AddFile() method. The key scenario for
which the WriteDelegate makes sense is saving a DataSet, in XML
format, to the zip file. The DataSet can write XML to a stream, and the
WriteDelegate is the perfect place to write into the zip file. There may be
other data structures that can write to a stream, but cannot be read as a
stream. The WriteDelegate would be appropriate for those cases as
well.
Private Sub WriteEntry (ByVal name As String, ByVal output As Stream)
Using input As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Dim n As Integer = -1
Dim buffer As Byte() = New Byte(BufferSize){}
Do While n <> 0
n = input.Read(buffer, 0, buffer.Length)
output.Write(buffer, 0, n)
Loop
End Using
End Sub
Public Sub Run()
Using zip = New ZipFile
zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry))
zip.Save(zipFileName)
End Using
End Sub
Remarks
When the application needs to write the zip entry data, use this method to add the ZipEntry. For example, in the case that the application wishes to write the XML representation of a DataSet into a ZipEntry, the application can use this method to do so.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
About progress events: When using the WriteDelegate, DotNetZip does
not issue any SaveProgress events with EventType =
Saving_EntryBytesRead. (This is because it is the
application's code that runs in WriteDelegate - there's no way for
DotNetZip to know when to issue a EntryBytesRead event.)
Applications that want to update a progress bar or similar status
indicator should do so from within the WriteDelegate
itself. DotNetZip will issue the other SaveProgress events,
including
Saving_Started,
Saving_BeforeWriteEntry, and
Saving_AfterWriteEntry.
Note: When you use PKZip encryption, it's normally necessary to compute the CRC of the content to be encrypted, before compressing or encrypting it. Therefore, when using PKZip encryption with a WriteDelegate, the WriteDelegate CAN BE called twice: once to compute the CRC, and the second time to potentially compress and encrypt. Surprising, but true. This is because PKWARE specified that the encryption initialization data depends on the CRC. If this happens, for each call of the delegate, your application must stream the same entry data in its entirety. If your application writes different data during the second call, it will result in a corrupt zip file.
The double-read behavior happens with all types of entries, not only those that use WriteDelegate. It happens if you add an entry from a filesystem file, or using a string, or a stream, or an opener/closer pair. But in those cases, DotNetZip takes care of reading twice; in the case of the WriteDelegate, the application code gets invoked twice. Be aware.
As you can imagine, this can cause performance problems for large
streams, and it can lead to correctness problems when you use a
WriteDelegate. This is a pretty big pitfall. There are two
ways to avoid it. First, and most preferred: don't use PKZIP
encryption. If you use the WinZip AES encryption, this problem
doesn't occur, because the encryption protocol doesn't require the CRC
up front. Second: if you do choose to use PKZIP encryption, write out
to a non-seekable stream (like standard output, or the
Response.OutputStream in an ASP.NET application). In this case,
DotNetZip will use an alternative encryption protocol that does not
rely on the CRC of the content. This also implies setting bit 3 in
the zip entry, which still presents problems for some zip tools.
In the future I may modify DotNetZip to *always* use bit 3 when PKZIP encryption is in use. This seems like a win overall, but there will be some work involved. If you feel strongly about it, visit the DotNetZip forums and vote up the Workitem tracking this issue.
AddEntry(string, byte[])
Add an entry into the zip archive using the given filename and directory path within the archive, and the given content for the file. No file is created in the filesystem.
public ZipEntry AddEntry(string entryName, byte[] byteContent)
Parameters
entryNamestringThe name, including any path, to use within the archive for the entry.
byteContentbyte[]The data to use for the entry.
Returns
- ZipEntry
The
ZipEntryadded.
AddEntry(string, Stream)
Create an entry in the ZipFile using the given Stream
as input. The entry will have the given filename.
public ZipEntry AddEntry(string entryName, Stream stream)
Parameters
entryNamestringThe name, including any path, which is shown in the zip file for the added entry.
streamStreamThe input stream from which to grab content for the file
Returns
- ZipEntry
The
ZipEntryadded.
Examples
This example adds a single entry to a ZipFile via a Stream.
String zipToCreate = "Content.zip";
String fileNameInArchive = "Content-From-Stream.bin";
using (System.IO.Stream streamToRead = MyStreamOpener())
{
using (ZipFile zip = new ZipFile())
{
ZipEntry entry= zip.AddEntry(fileNameInArchive, streamToRead);
zip.AddFile("Readme.txt");
zip.Save(zipToCreate); // the stream is read implicitly here
}
}
Dim zipToCreate As String = "Content.zip"
Dim fileNameInArchive As String = "Content-From-Stream.bin"
Using streamToRead as System.IO.Stream = MyStreamOpener()
Using zip As ZipFile = New ZipFile()
Dim entry as ZipEntry = zip.AddEntry(fileNameInArchive, streamToRead)
zip.AddFile("Readme.txt")
zip.Save(zipToCreate) '' the stream is read implicitly, here
End Using
End Using
Remarks
The application should provide an open, readable stream; in this case it will be read during the call to Save() or one of its overloads.
The passed stream will be read from its current position. If necessary, callers should set the position in the stream before calling AddEntry(). This might be appropriate when using this method with a MemoryStream, for example.
In cases where a large number of streams will be added to the
ZipFile, the application may wish to avoid maintaining all of the
streams open simultaneously. To handle this situation, the application
should use the AddEntry(string, OpenDelegate, CloseDelegate)
overload.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
AddEntry(string, string)
Adds a named entry into the zip archive, taking content for the entry from a string.
public ZipEntry AddEntry(string entryName, string content)
Parameters
entryNamestringThe name, including any path, to use for the entry within the archive.
contentstringThe content of the file, should it be extracted from the zip.
Returns
- ZipEntry
The
ZipEntryadded.
Examples
This example shows how to add an entry to the zipfile, using a string as content for that entry.
string Content = "This string will be the content of the Readme.txt file in the zip archive.";
using (ZipFile zip1 = new ZipFile())
{
zip1.AddFile("MyDocuments\\Resume.doc", "files");
zip1.AddEntry("Readme.txt", Content);
zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G");
zip1.Save("Content.zip");
}
Public Sub Run()
Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive."
Using zip1 As ZipFile = New ZipFile
zip1.AddEntry("Readme.txt", Content)
zip1.AddFile("MyDocuments\Resume.doc", "files")
zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G"))
zip1.Save("Content.zip")
End Using
End Sub
Remarks
Calling this method creates an entry using the given fileName and directory path within the archive. There is no need for a file by the given name to exist in the filesystem; the name is used within the zip archive only. The content for the entry is encoded using the default text encoding for the machine.
AddEntry(string, string, Encoding)
Adds a named entry into the zip archive, taking content for the entry from a string, and using the specified text encoding.
public ZipEntry AddEntry(string entryName, string content, Encoding encoding)
Parameters
entryNamestringThe name, including any path, to use within the archive for the entry.
contentstringThe content of the file, should it be extracted from the zip.
encodingEncodingThe text encoding to use when encoding the string. Be aware: This is distinct from the text encoding used to encode the fileName, as specified in ProvisionalAlternateEncoding.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
Calling this method creates an entry using the given fileName and directory path within the archive. There is no need for a file by the given name to exist in the filesystem; the name is used within the zip archive only.
The content for the entry, a string value, is encoded using the given text encoding. A BOM (byte-order-mark) is emitted into the file, if the Encoding parameter is set for that.
Most Encoding classes support a constructor that accepts a boolean, indicating whether to emit a BOM or not. For example see UTF8Encoding(bool).
AddFile(string)
Adds a File to a Zip file archive.
public ZipEntry AddFile(string fileName)
Parameters
fileNamestringThe name of the file to add. It should refer to a file in the filesystem. The name of the file may be a relative path or a fully-qualified path.
Returns
- ZipEntry
The
ZipEntrycorresponding to the File added.
Examples
In this example, three files are added to a Zip archive. The ReadMe.txt file will be placed in the root of the archive. The .png file will be placed in a folder within the zip called photos\personal. The pdf file will be included into a folder within the zip called Desktop.
try
{
using (ZipFile zip = new ZipFile())
{
zip.AddFile("c:\\photos\\personal\\7440-N49th.png");
zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf");
zip.AddFile("ReadMe.txt");
zip.Save("Package.zip");
}
}
catch (System.Exception ex1)
{
System.Console.Error.WriteLine("exception: " + ex1);
}
Try
Using zip As ZipFile = New ZipFile
zip.AddFile("c:\photos\personal\7440-N49th.png")
zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf")
zip.AddFile("ReadMe.txt")
zip.Save("Package.zip")
End Using
Catch ex1 As Exception
Console.Error.WriteLine("exception: {0}", ex1.ToString)
End Try
Remarks
This call collects metadata for the named file in the filesystem,
including the file attributes and the timestamp, and inserts that metadata
into the resulting ZipEntry. Only when the application calls Save() on
the ZipFile, does DotNetZip read the file from the filesystem and
then write the content to the zip file archive.
This method will throw an exception if an entry with the same name already
exists in the ZipFile.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
AddFile(string, string)
Adds a File to a Zip file archive, potentially overriding the path to be used within the zip archive.
public ZipEntry AddFile(string fileName, string directoryPathInArchive)
Parameters
fileNamestringThe name of the file to add. The name of the file may be a relative path or a fully-qualified path.
directoryPathInArchivestringSpecifies a directory path to use to override any path in the fileName. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passing
null(Nothingin VB) will use the path on the fileName, if any. Passing the empty string ("") will insert the item at the root path within the archive.
Returns
- ZipEntry
The
ZipEntrycorresponding to the file added.
Examples
In this example, three files are added to a Zip archive. The ReadMe.txt file will be placed in the root of the archive. The .png file will be placed in a folder within the zip called images. The pdf file will be included into a folder within the zip called files\docs, and will be encrypted with the given password.
try
{
using (ZipFile zip = new ZipFile())
{
// the following entry will be inserted at the root in the archive.
zip.AddFile("c:\\datafiles\\ReadMe.txt", "");
// this image file will be inserted into the "images" directory in the archive.
zip.AddFile("c:\\photos\\personal\\7440-N49th.png", "images");
// the following will result in a password-protected file called
// files\\docs\\2008-Regional-Sales-Report.pdf in the archive.
zip.Password = "EncryptMe!";
zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf", "files\\docs");
zip.Save("Archive.zip");
}
}
catch (System.Exception ex1)
{
System.Console.Error.WriteLine("exception: {0}", ex1);
}
Try
Using zip As ZipFile = New ZipFile
' the following entry will be inserted at the root in the archive.
zip.AddFile("c:\datafiles\ReadMe.txt", "")
' this image file will be inserted into the "images" directory in the archive.
zip.AddFile("c:\photos\personal\7440-N49th.png", "images")
' the following will result in a password-protected file called
' files\\docs\\2008-Regional-Sales-Report.pdf in the archive.
zip.Password = "EncryptMe!"
zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf", "files\documents")
zip.Save("Archive.zip")
End Using
Catch ex1 As Exception
Console.Error.WriteLine("exception: {0}", ex1)
End Try
Remarks
The file added by this call to the ZipFile is not written to the
zip file archive until the application calls Save() on the ZipFile.
This method will throw an exception if an entry with the same name already
exists in the ZipFile.
This version of the method allows the caller to explicitly specify the directory path to be used in the archive.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
AddFiles(IEnumerable<string>)
This method adds a set of files to the ZipFile.
public void AddFiles(IEnumerable<string> fileNames)
Parameters
fileNamesIEnumerable<string>The collection of names of the files to add. Each string should refer to a file in the filesystem. The name of the file may be a relative path or a fully-qualified path.
Examples
This example shows how to create a zip file, and add a few files into it.
String ZipFileToCreate = "archive1.zip";
String DirectoryToZip = "c:\\reports";
using (ZipFile zip = new ZipFile())
{
// Store all files found in the top level directory, into the zip archive.
String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
zip.AddFiles(filenames);
zip.Save(ZipFileToCreate);
}
Dim ZipFileToCreate As String = "archive1.zip"
Dim DirectoryToZip As String = "c:\reports"
Using zip As ZipFile = New ZipFile
' Store all files found in the top level directory, into the zip archive.
Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
zip.AddFiles(filenames)
zip.Save(ZipFileToCreate)
End Using
Remarks
Use this method to add a set of files to the zip archive, in one call.
For example, a list of files received from
System.IO.Directory.GetFiles() can be added to a zip archive in one
call.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to each
ZipEntry added.
- See Also
AddFiles(IEnumerable<string>, bool, string)
Adds a set of files to the ZipFile, using the specified directory
path in the archive, and preserving the full directory structure in the
filenames.
public void AddFiles(IEnumerable<string> fileNames, bool preserveDirHierarchy, string directoryPathInArchive)
Parameters
fileNamesIEnumerable<string>The names of the files to add. Each string should refer to a file in the filesystem. The name of the file may be a relative path or a fully-qualified path.
preserveDirHierarchyboolwhether the entries in the zip archive will reflect the directory hierarchy that is present in the various filenames. For example, if
fileNamesincludes two paths, \Animalia\Chordata\Mammalia\Info.txt and \Plantae\Magnoliophyta\Dicotyledon\Info.txt, then calling this method withpreserveDirHierarchy=falsewill result in an exception because of a duplicate entry name, while calling this method withpreserveDirHierarchy=truewill result in the full direcory paths being included in the entries added to the ZipFile.directoryPathInArchivestringSpecifies a directory path to use as a prefix for each entry name. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passing
null(Nothingin VB) will use the path on each of thefileNames, if any. Passing the empty string ("") will insert the item at the root path within the archive.
Remarks
Think of the directoryPathInArchive as a "root" or
base directory used in the archive for the files that get added. when
preserveDirHierarchy is true, the hierarchy of files
found in the filesystem will be placed, with the hierarchy intact,
starting at that root in the archive. When preserveDirHierarchy
is false, the path hierarchy of files is flattned, and the flattened
set of files gets placed in the root within the archive as specified in
directoryPathInArchive.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to each
ZipEntry added.
- See Also
AddFiles(IEnumerable<string>, string)
Adds a set of files to the ZipFile, using the
specified directory path in the archive.
public void AddFiles(IEnumerable<string> fileNames, string directoryPathInArchive)
Parameters
fileNamesIEnumerable<string>The names of the files to add. Each string should refer to a file in the filesystem. The name of the file may be a relative path or a fully-qualified path.
directoryPathInArchivestringSpecifies a directory path to use to override any path in the file name. Th is path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passing
null(Nothingin VB) will use the path on each of thefileNames, if any. Passing the empty string ("") will insert the item at the root path within the archive.
Remarks
Any directory structure that may be present in the filenames contained in the list is "flattened" in the archive. Each file in the list is added to the archive in the specified top-level directory.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile, ZipErrorAction, and CompressionLevel, their respective values at the
time of this call will be applied to each ZipEntry added.
- See Also
AddItem(string)
Adds an item, either a file or a directory, to a zip file archive.
public ZipEntry AddItem(string fileOrDirectoryName)
Parameters
fileOrDirectoryNamestringthe name of the file or directory to add.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
This method is handy if you are adding things to zip archive and don't
want to bother distinguishing between directories or files. Any files are
added as single entries. A directory added through this method is added
recursively: all files and subdirectories contained within the directory
are added to the ZipFile.
The name of the item may be a relative path or a fully-qualified
path. Remember, the items contained in ZipFile instance get written
to the disk only when you call Save() or a similar
save method.
The directory name used for the file within the archive is the same
as the directory name (potentially a relative path) specified in the
fileOrDirectoryName.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
AddItem(string, string)
Adds an item, either a file or a directory, to a zip file archive, explicitly specifying the directory path to be used in the archive.
public ZipEntry AddItem(string fileOrDirectoryName, string directoryPathInArchive)
Parameters
fileOrDirectoryNamestringthe name of the file or directory to add.
directoryPathInArchivestringThe name of the directory path to use within the zip archive. This path need not refer to an extant directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passing
null(Nothingin VB) will use the path on the fileOrDirectoryName. Passing the empty string ("") will insert the item at the root path within the archive.
Returns
- ZipEntry
The
ZipEntryadded.
Examples
This example shows how to zip up a set of files into a flat hierarchy, regardless of where in the filesystem the files originated. The resulting zip archive will contain a toplevel directory named "flat", which itself will contain files Readme.txt, MyProposal.docx, and Image1.jpg. A subdirectory under "flat" called SupportFiles will contain all the files in the "c:\SupportFiles" directory on disk.
String[] itemnames= {
"c:\\fixedContent\\Readme.txt",
"MyProposal.docx",
"c:\\SupportFiles", // a directory
"images\\Image1.jpg"
};
try
{
using (ZipFile zip = new ZipFile())
{
for (int i = 1; i < itemnames.Length; i++)
{
// will add Files or Dirs, recurses and flattens subdirectories
zip.AddItem(itemnames[i],"flat");
}
zip.Save(ZipToCreate);
}
}
catch (System.Exception ex1)
{
System.Console.Error.WriteLine("exception: {0}", ex1);
}
Dim itemnames As String() = _
New String() { "c:\fixedContent\Readme.txt", _
"MyProposal.docx", _
"SupportFiles", _
"images\Image1.jpg" }
Try
Using zip As New ZipFile
Dim i As Integer
For i = 1 To itemnames.Length - 1
' will add Files or Dirs, recursing and flattening subdirectories.
zip.AddItem(itemnames(i), "flat")
Next i
zip.Save(ZipToCreate)
End Using
Catch ex1 As Exception
Console.Error.WriteLine("exception: {0}", ex1.ToString())
End Try
Remarks
If adding a directory, the add is recursive on all files and subdirectories contained within it.
The name of the item may be a relative path or a fully-qualified path.
The item added by this call to the ZipFile is not read from the
disk nor written to the zip file archive until the application calls
Save() on the ZipFile.
This version of the method allows the caller to explicitly specify the directory path to be used in the archive, which would override the "natural" path of the filesystem file.
Encryption will be used on the file data if the Password has
been set on the ZipFile object, prior to calling this method.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
Exceptions
- FileNotFoundException
Thrown if the file or directory passed in does not exist.
- See Also
AddSelectedFiles(string)
Adds to the ZipFile a set of files from the current working directory on disk, that conform to the specified criteria.
public void AddSelectedFiles(string selectionCriteria)
Parameters
selectionCriteriastringThe criteria for file selection
Examples
This example zips up all *.csv files in the current working directory.
using (ZipFile zip = new ZipFile())
{
// To just match on filename wildcards,
// use the shorthand form of the selectionCriteria string.
zip.AddSelectedFiles("*.csv");
zip.Save(PathToZipArchive);
}
Using zip As ZipFile = New ZipFile()
zip.AddSelectedFiles("*.csv")
zip.Save(PathToZipArchive)
End Using
Remarks
This method selects files from the the current working directory matching the specified criteria, and adds them to the ZipFile.
Specify the criteria in statements of 3 elements: a noun, an operator, and a value. Consider the string "name != *.doc" . The noun is "name". The operator is "!=", implying "Not Equal". The value is "*.doc". That criterion, in English, says "all files with a name that does not end in the .doc extension."
Supported nouns include "name" (or "filename") for the filename; "atime", "mtime", and "ctime" for last access time, last modfied time, and created time of the file, respectively; "attributes" (or "attrs") for the file attributes; "size" (or "length") for the file length (uncompressed), and "type" for the type of object, either a file or a directory. The "attributes", "name" and "type" nouns both support = and != as operators. The "size", "atime", "mtime", and "ctime" nouns support = and !=, and >, >=, <, <= as well. The times are taken to be expressed in local time.
Specify values for the file attributes as a string with one or more of the characters H,R,text,A,I,L in any order, implying file attributes of Hidden, ReadOnly, System, Archive, NotContextIndexed, and ReparsePoint (symbolic link) respectively.
To specify a time, use YYYY-MM-DD-HH:mm:ss or YYYY/MM/DD-HH:mm:ss as the format. If you omit the HH:mm:ss portion, it is assumed to be 00:00:00 (midnight).
The value for a size criterion is expressed in integer quantities of bytes, kilobytes (use k or kb after the number), megabytes (m or mb), or gigabytes (g or gb).
The value for a name is a pattern to match against the filename, potentially including wildcards. The pattern follows CMD.exe glob rules: * implies one or more of any character, while ? implies one character. If the name pattern contains any slashes, it is matched to the entire filename, including the path; otherwise, it is matched against only the filename without the path. This means a pattern of "*\*.*" matches all files one directory level deep, while a pattern of "*.*" matches all files in all directories.
To specify a name pattern that includes spaces, use single quotes around the pattern. A pattern of "'* *.*'" will match all files that have spaces in the filename. The full criteria string for that would be "name = '* *.*'" .
The value for a type criterion is either F (implying a file) or D (implying a directory).
Some examples:
| criteria | Files retrieved |
|---|---|
| name != *.xls | any file with an extension that is not .xls |
| name = *.mp3 | any file with a .mp3 extension. |
| *.mp3 | (same as above) any file with a .mp3 extension. |
| attributes = A | all files whose attributes include the Archive bit. |
| attributes != H | all files whose attributes do not include the Hidden bit. |
| mtime > 2009-01-01 | all files with a last modified time after January 1st, 2009. |
| size > 2gb | all files whose uncompressed size is greater than 2gb. |
| type = D | all directories in the filesystem. |
You can combine criteria with the conjunctions AND or OR. Using a string like "name = *.txt AND size >= 100k" for the selectionCriteria retrieves entries whose names end in .txt, and whose uncompressed size is greater than or equal to 100 kilobytes.
For more complex combinations of criteria, you can use parenthesis to group clauses in the boolean logic. Without parenthesis, the precedence of the criterion atoms is determined by order of appearance. Unlike the C# language, the AND conjunction does not take precendence over the logical OR. This is important only in strings that contain 3 or more criterion atoms. In other words, "name = *.txt and size > 1000 or attributes = H" implies "((name = *.txt AND size > 1000) OR attributes = H)" while "attributes = H OR name = *.txt and size > 1000" evaluates to "((attributes = H OR name = *.txt) AND size > 1000)". When in doubt, use parenthesis.
Using time properties requires some extra care. If you want to retrieve all entries that were last updated on 2009 February 14, specify a time range like so:"mtime >= 2009-02-14 AND mtime < 2009-02-15". Read this to say: all files updated after 12:00am on February 14th, until 12:00am on February 15th. You can use the same bracketing approach to specify any time period - a year, a month, a week, and so on.
The syntax allows one special case: if you provide a string with no spaces, it is treated as a pattern to match for the filename. Therefore a string like "*.xls" will be equivalent to specifying "name = *.xls".
There is no logic in this method that insures that the file inclusion criteria are internally consistent. For example, it's possible to specify criteria that says the file must have a size of less than 100 bytes, as well as a size that is greater than 1000 bytes. Obviously no file will ever satisfy such criteria, but this method does not detect such logical inconsistencies. The caller is responsible for insuring the criteria are sensible.
Using this method, the file selection does not recurse into subdirectories, and the full path of the selected files is included in the entries added into the zip archive. If you don't like these behaviors, see the other overloads of this method.
AddSelectedFiles(string, bool)
Adds to the ZipFile a set of files from the disk that conform to the specified criteria, optionally recursing into subdirectories.
public void AddSelectedFiles(string selectionCriteria, bool recurseDirectories)
Parameters
selectionCriteriastringThe criteria for file selection
recurseDirectoriesboolIf true, the file selection will recurse into subdirectories.
Examples
This example zips up all *.xml files in the current working directory, or any subdirectory, that are larger than 1mb.
using (ZipFile zip = new ZipFile())
{
// Use a compound expression in the selectionCriteria string.
zip.AddSelectedFiles("name = *.xml and size > 1024kb", true);
zip.Save(PathToZipArchive);
}
Using zip As ZipFile = New ZipFile()
' Use a compound expression in the selectionCriteria string.
zip.AddSelectedFiles("name = *.xml and size > 1024kb", true)
zip.Save(PathToZipArchive)
End Using
Remarks
This method selects files from the the current working directory matching
the specified criteria, and adds them to the ZipFile. If
recurseDirectories is true, files are also selected from
subdirectories, and the directory structure in the filesystem is
reproduced in the zip archive, rooted at the current working directory.
Using this method, the full path of the selected files is included in the
entries added into the zip archive. If you don't want this behavior, use
one of the overloads of this method that allows the specification of a
directoryInArchive.
For details on the syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
AddSelectedFiles(string, string)
Adds to the ZipFile a set of files from a specified directory in the filesystem, that conform to the specified criteria.
public void AddSelectedFiles(string selectionCriteria, string directoryOnDisk)
Parameters
selectionCriteriastringThe criteria for file selection
directoryOnDiskstringThe name of the directory on the disk from which to select files.
Examples
This example zips up all *.xml files larger than 1mb in the directory given by "d:\rawdata".
using (ZipFile zip = new ZipFile())
{
// Use a compound expression in the selectionCriteria string.
zip.AddSelectedFiles("name = *.xml and size > 1024kb", "d:\\rawdata");
zip.Save(PathToZipArchive);
}
Using zip As ZipFile = New ZipFile()
' Use a compound expression in the selectionCriteria string.
zip.AddSelectedFiles("name = *.xml and size > 1024kb", "d:\rawdata)
zip.Save(PathToZipArchive)
End Using
Remarks
This method selects files that conform to the specified criteria, from the the specified directory on disk, and adds them to the ZipFile. The search does not recurse into subdirectores.
Using this method, the full filesystem path of the files on disk is reproduced on the entries added to the zip file. If you don't want this behavior, use one of the other overloads of this method.
For details on the syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
AddSelectedFiles(string, string, bool)
Adds to the ZipFile a set of files from the specified directory on disk, that conform to the specified criteria.
public void AddSelectedFiles(string selectionCriteria, string directoryOnDisk, bool recurseDirectories)
Parameters
selectionCriteriastringThe criteria for file selection
directoryOnDiskstringThe filesystem path from which to select files.
recurseDirectoriesboolIf true, the file selection will recurse into subdirectories.
Examples
This example zips up all *.csv files in the "files" directory, or any subdirectory, that have been saved since 2009 February 14th.
using (ZipFile zip = new ZipFile())
{
// Use a compound expression in the selectionCriteria string.
zip.AddSelectedFiles("name = *.csv and mtime > 2009-02-14", "files", true);
zip.Save(PathToZipArchive);
}
Using zip As ZipFile = New ZipFile()
' Use a compound expression in the selectionCriteria string.
zip.AddSelectedFiles("name = *.csv and mtime > 2009-02-14", "files", true)
zip.Save(PathToZipArchive)
End Using
This example zips up all files in the current working
directory, and all its child directories, except those in
the excludethis subdirectory.
Using Zip As ZipFile = New ZipFile(zipfile)
Zip.AddSelectedFfiles("name != 'excludethis\*.*'", datapath, True)
Zip.Save()
End Using
Remarks
This method selects files from the the specified disk directory matching
the specified selection criteria, and adds them to the ZipFile. If
recurseDirectories is true, files are also selected from
subdirectories.
The full directory structure in the filesystem is reproduced on the
entries added to the zip archive. If you don't want this behavior, use
one of the overloads of this method that allows the specification of a
directoryInArchive.
For details on the syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
AddSelectedFiles(string, string, string)
Adds to the ZipFile a selection of files from the specified directory on disk, that conform to the specified criteria, and using a specified root path for entries added to the zip archive.
public void AddSelectedFiles(string selectionCriteria, string directoryOnDisk, string directoryPathInArchive)
Parameters
selectionCriteriastringThe criteria for selection of files to add to the
ZipFile.directoryOnDiskstringThe path to the directory in the filesystem from which to select files.
directoryPathInArchivestringSpecifies a directory path to use to in place of the
directoryOnDisk. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passing null (nothing in VB) will use the path on the file name, if any; in other words it would usedirectoryOnDisk, plus any subdirectory. Passing the empty string ("") will insert the item at the root path within the archive.
Examples
This example zips up all *.psd files in the "photos" directory that have been saved since 2009 February 14th, and puts them all in a zip file, using the directory name of "content" in the zip archive itself. When the zip archive is unzipped, the folder containing the .psd files will be named "content".
using (ZipFile zip = new ZipFile())
{
// Use a compound expression in the selectionCriteria string.
zip.AddSelectedFiles("name = *.psd and mtime > 2009-02-14", "photos", "content");
zip.Save(PathToZipArchive);
}
Using zip As ZipFile = New ZipFile
zip.AddSelectedFiles("name = *.psd and mtime > 2009-02-14", "photos", "content")
zip.Save(PathToZipArchive)
End Using
Remarks
This method selects files from the specified disk directory matching the specified selection criteria, and adds those files to the ZipFile, using the specified directory path in the archive. The search does not recurse into subdirectories. For details on the syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
AddSelectedFiles(string, string, string, bool)
Adds to the ZipFile a selection of files from the specified directory on disk, that conform to the specified criteria, optionally recursing through subdirectories, and using a specified root path for entries added to the zip archive.
public void AddSelectedFiles(string selectionCriteria, string directoryOnDisk, string directoryPathInArchive, bool recurseDirectories)
Parameters
selectionCriteriastringThe criteria for selection of files to add to the
ZipFile.directoryOnDiskstringThe path to the directory in the filesystem from which to select files.
directoryPathInArchivestringSpecifies a directory path to use to in place of the
directoryOnDisk. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passing null (nothing in VB) will use the path on the file name, if any; in other words it would usedirectoryOnDisk, plus any subdirectory. Passing the empty string ("") will insert the item at the root path within the archive.recurseDirectoriesboolIf true, the method also scans subdirectories for files matching the criteria.
Examples
This example zips up all files that are NOT *.pst files, in the current working directory and any subdirectories.
using (ZipFile zip = new ZipFile())
{
zip.AddSelectedFiles("name != *.pst", SourceDirectory, "backup", true);
zip.Save(PathToZipArchive);
}
Using zip As ZipFile = New ZipFile
zip.AddSelectedFiles("name != *.pst", SourceDirectory, "backup", true)
zip.Save(PathToZipArchive)
End Using
Remarks
This method selects files from the specified disk directory that match the
specified selection criteria, and adds those files to the ZipFile, using
the specified directory path in the archive. If recurseDirectories
is true, files are also selected from subdirectories, and the directory
structure in the filesystem is reproduced in the zip archive, rooted at
the directory specified by directoryOnDisk. For details on the
syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
CheckZip(string)
Checks a zip file to see if its directory is consistent.
public static bool CheckZip(string zipFileName)
Parameters
zipFileNamestringThe filename to of the zip file to check.
Returns
- bool
true if the named zip file checks OK. Otherwise, false.
Remarks
In cases of data error, the directory within a zip file can get out of synch with the entries in the zip file. This method checks the given zip file and returns true if this has occurred.
This method may take a long time to run for large zip files.
This method is not supported in the Reduced version of DotNetZip.
Developers using COM can use the ComHelper.CheckZip(String) method.
- See Also
CheckZip(string, bool, TextWriter)
Checks a zip file to see if its directory is consistent, and optionally fixes the directory if necessary.
public static bool CheckZip(string zipFileName, bool fixIfNecessary, TextWriter writer)
Parameters
zipFileNamestringThe filename to of the zip file to check.
fixIfNecessaryboolIf true, the method will fix the zip file if necessary.
writerTextWritera TextWriter in which messages generated while checking will be written.
Returns
- bool
true if the named zip is OK; false if the file needs to be fixed.
Remarks
In cases of data error, the directory within a zip file can get out of synch with the entries in the zip file. This method checks the given zip file, and returns true if this has occurred. It also optionally fixes the zipfile, saving the fixed copy in Name_Fixed.zip.
This method may take a long time to run for large zip files. It
will take even longer if the file actually needs to be fixed, and if
fixIfNecessary is true.
This method is not supported in the Reduced version of DotNetZip.
- See Also
CheckZipPassword(string, string)
Verify the password on a zip file.
public static bool CheckZipPassword(string zipFileName, string password)
Parameters
Returns
- bool
a bool indicating whether the password matches.
Remarks
Keep in mind that passwords in zipfiles are applied to zip entries, not to the entire zip file. So testing a zipfile for a particular password doesn't work in the general case. On the other hand, it's often the case that a single password will be used on all entries in a zip file. This method works for that case.
There is no way to check a password without doing the decryption. So this code decrypts and extracts the given zipfile into Null
ContainsEntry(string)
Returns true if an entry by the given name exists in the ZipFile.
public bool ContainsEntry(string name)
Parameters
namestringthe name of the entry to find
Returns
- bool
true if an entry with the given name exists; otherwise false.
Dispose()
Closes the read and write streams associated
to the ZipFile, if necessary.
public void Dispose()
Examples
This example extracts an entry selected by name, from the Zip file to the Console.
using (ZipFile zip = ZipFile.Read(zipfile))
{
foreach (ZipEntry e in zip)
{
if (WantThisEntry(e.FileName))
zip.Extract(e.FileName, Console.OpenStandardOutput());
}
} // Dispose() is called implicitly here.
Using zip As ZipFile = ZipFile.Read(zipfile)
Dim e As ZipEntry
For Each e In zip
If WantThisEntry(e.FileName) Then
zip.Extract(e.FileName, Console.OpenStandardOutput())
End If
Next
End Using ' Dispose is implicity called here
Remarks
The Dispose() method is generally employed implicitly, via a using(..) {..}
statement. (Using...End Using in VB) If you do not employ a using
statement, insure that your application calls Dispose() explicitly. For
example, in a Powershell application, or an application that uses the COM
interop interface, you must call Dispose() explicitly.
Dispose(bool)
Disposes any managed resources, if the flag is set, then marks the instance disposed. This method is typically not called explicitly from application code.
protected virtual void Dispose(bool disposeManagedResources)
Parameters
disposeManagedResourcesboolindicates whether the method should dispose streams or not.
Remarks
Applications should call the no-arg Dispose method.
ExtractAll(string)
Extracts all of the items in the zip archive, to the specified path in the filesystem. The path can be relative or fully-qualified.
public void ExtractAll(string path)
Parameters
pathstringThe path to which the contents of the zipfile will be extracted. The path can be relative or fully-qualified.
Examples
This example extracts all the entries in a zip archive file, to the specified target directory. The extraction will overwrite any existing files silently.
String TargetDirectory= "unpack";
using(ZipFile zip= ZipFile.Read(ZipFileToExtract))
{
zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently;
zip.ExtractAll(TargetDirectory);
}
Dim TargetDirectory As String = "unpack"
Using zip As ZipFile = ZipFile.Read(ZipFileToExtract)
zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently
zip.ExtractAll(TargetDirectory)
End Using
Remarks
This method will extract all entries in the ZipFile to the
specified path.
If an extraction of a file from the zip archive would overwrite an
existing file in the filesystem, the action taken is dictated by the
ExtractExistingFile property, which overrides any setting you may have
made on individual ZipEntry instances. By default, if you have not
set that property on the ZipFile instance, the entry will not
be extracted, the existing file will not be overwritten and an
exception will be thrown. To change this, set the property, or use the
ExtractAll(string, ExtractExistingFileAction) overload that allows you to
specify an ExtractExistingFileAction parameter.
The action to take when an extract would overwrite an existing file applies to all entries. If you want to set this on a per-entry basis, then you must use one of the ZipEntry.Extract methods.
This method will send verbose output messages to the StatusMessageTextWriter, if it is set on the ZipFile
instance.
You may wish to take advantage of the ExtractProgress event.
About timestamps: When extracting a file entry from a zip archive, the
extracted file gets the last modified time of the entry as stored in
the archive. The archive may also store extended file timestamp
information, including last accessed and created times. If these are
present in the ZipEntry, then the extracted file will also get
these times.
A Directory entry is somewhat different. It will get the times as described for a file entry, but, if there are file entries in the zip archive that, when extracted, appear in the just-created directory, then when those file entries are extracted, the last modified and last accessed times of the directory will change, as a side effect. The result is that after an extraction of a directory and a number of files within the directory, the last modified and last accessed timestamps on the directory will reflect the time that the last file was extracted into the directory, rather than the time stored in the zip archive for the directory.
To compensate, when extracting an archive with ExtractAll,
DotNetZip will extract all the file and directory entries as described
above, but it will then make a second pass on the directories, and
reset the times on the directories to reflect what is stored in the
zip archive.
This compensation is performed only within the context of an
ExtractAll. If you call ZipEntry.Extract on a directory
entry, the timestamps on directory in the filesystem will reflect the
times stored in the zip. If you then call ZipEntry.Extract on
a file entry, which is extracted into the directory, the timestamps on
the directory will be updated to the current time.
- See Also
ExtractAll(string, ExtractExistingFileAction)
Extracts all of the items in the zip archive, to the specified path in the filesystem, using the specified behavior when extraction would overwrite an existing file.
public void ExtractAll(string path, ExtractExistingFileAction extractExistingFile)
Parameters
pathstringThe path to which the contents of the zipfile will be extracted. The path can be relative or fully-qualified.
extractExistingFileExtractExistingFileActionThe action to take if extraction would overwrite an existing file.
Examples
This example extracts all the entries in a zip archive file, to the specified target directory. It does not overwrite any existing files.
String TargetDirectory= "c:\\unpack";
using(ZipFile zip= ZipFile.Read(ZipFileToExtract))
{
zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite);
}
Dim TargetDirectory As String = "c:\unpack"
Using zip As ZipFile = ZipFile.Read(ZipFileToExtract)
zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite)
End Using
Remarks
This method will extract all entries in the ZipFile to the specified
path. For an extraction that would overwrite an existing file, the behavior
is dictated by extractExistingFile, which overrides any
setting you may have made on individual ZipEntry instances.
The action to take when an extract would overwrite an existing file applies to all entries. If you want to set this on a per-entry basis, then you must use Extract(string, ExtractExistingFileAction) or one of the similar methods.
Calling this method is equivalent to setting the ExtractExistingFile property and then calling ExtractAll(string).
This method will send verbose output messages to the
StatusMessageTextWriter, if it is set on the ZipFile instance.
- See Also
ExtractSelectedEntries(string)
Selects and Extracts a set of Entries from the ZipFile.
public void ExtractSelectedEntries(string selectionCriteria)
Parameters
selectionCriteriastringthe selection criteria for entries to extract.
Examples
This example shows how extract all XML files modified after 15 January 2009.
using (ZipFile zip = ZipFile.Read(zipArchiveName))
{
zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15");
}
Remarks
The entries are extracted into the current working directory.
If any of the files to be extracted already exist, then the action taken is as specified in the ExtractExistingFile property on the corresponding ZipEntry instance. By default, the action taken in this case is to throw an exception.
For information on the syntax of the selectionCriteria string, see AddSelectedFiles(string).
- See Also
ExtractSelectedEntries(string, ExtractExistingFileAction)
Selects and Extracts a set of Entries from the ZipFile.
public void ExtractSelectedEntries(string selectionCriteria, ExtractExistingFileAction extractExistingFile)
Parameters
selectionCriteriastringthe selection criteria for entries to extract.
extractExistingFileExtractExistingFileActionThe action to take if extraction would overwrite an existing file.
Examples
This example shows how extract all XML files modified after 15 January 2009, overwriting any existing files.
using (ZipFile zip = ZipFile.Read(zipArchiveName))
{
zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15",
ExtractExistingFileAction.OverwriteSilently);
}
Remarks
The entries are extracted into the current working directory. When extraction would would
overwrite an existing filesystem file, the action taken is as specified in the
extractExistingFile parameter.
For information on the syntax of the string describing the entry selection criteria, see AddSelectedFiles(string).
ExtractSelectedEntries(string, string)
Selects and Extracts a set of Entries from the ZipFile.
public void ExtractSelectedEntries(string selectionCriteria, string directoryPathInArchive)
Parameters
selectionCriteriastringthe selection criteria for entries to extract.
directoryPathInArchivestringthe directory in the archive from which to select entries. If null, then all directories in the archive are used.
Examples
This example shows how extract all XML files modified after 15 January 2009, and writes them to the "unpack" directory.
using (ZipFile zip = ZipFile.Read(zipArchiveName))
{
zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15","unpack");
}
Remarks
The entries are selected from the specified directory within the archive, and then extracted into the current working directory.
If any of the files to be extracted already exist, then the action taken is as specified in the ExtractExistingFile property on the corresponding ZipEntry instance. By default, the action taken in this case is to throw an exception.
For information on the syntax of the string describing the entry selection criteria, see AddSelectedFiles(string).
- See Also
ExtractSelectedEntries(string, string, string)
Selects and Extracts a set of Entries from the ZipFile.
public void ExtractSelectedEntries(string selectionCriteria, string directoryInArchive, string extractDirectory)
Parameters
selectionCriteriastringthe selection criteria for entries to extract.
directoryInArchivestringthe directory in the archive from which to select entries. If null, then all directories in the archive are used.
extractDirectorystringthe directory on the disk into which to extract. It will be created if it does not exist.
Remarks
The entries are extracted into the specified directory. If any of the files to be extracted already exist, an exception will be thrown.
For information on the syntax of the string describing the entry selection criteria, see AddSelectedFiles(string).
ExtractSelectedEntries(string, string, string, ExtractExistingFileAction)
Selects and Extracts a set of Entries from the ZipFile.
public void ExtractSelectedEntries(string selectionCriteria, string directoryPathInArchive, string extractDirectory, ExtractExistingFileAction extractExistingFile)
Parameters
selectionCriteriastringthe selection criteria for entries to extract.
directoryPathInArchivestringThe directory in the archive from which to select entries. If null, then all directories in the archive are used.
extractDirectorystringThe directory on the disk into which to extract. It will be created if it does not exist.
extractExistingFileExtractExistingFileActionThe action to take if extraction would overwrite an existing file.
Examples
This example shows how extract all files with an XML extension or with a size larger than 100,000 bytes, and puts them in the unpack directory. For any files that already exist in that destination directory, they will not be overwritten.
using (ZipFile zip = ZipFile.Read(zipArchiveName))
{
zip.ExtractSelectedEntries("name = *.xml or size > 100000",
null,
"unpack",
ExtractExistingFileAction.DontOverwrite);
}
Remarks
The entries are extracted into the specified directory. When extraction would would
overwrite an existing filesystem file, the action taken is as specified in the
extractExistingFile parameter.
For information on the syntax of the string describing the entry selection criteria, see AddSelectedFiles(string).
FixZipDirectory(string)
Rewrite the directory within a zipfile.
public static void FixZipDirectory(string zipFileName)
Parameters
zipFileNamestringThe filename to of the zip file to fix.
Remarks
In cases of data error, the directory in a zip file can get out of synch with the entries in the zip file. This method attempts to fix the zip file if this has occurred.
This can take a long time for large zip files.
This won't work if the zip file uses a non-standard code page - neither IBM437 nor UTF-8.
This method is not supported in the Reduced or Compact Framework versions of DotNetZip.
Developers using COM can use the ComHelper.FixZipDirectory(String) method.
- See Also
GetEnumerator()
Generic IEnumerator support, for use of a ZipFile in an enumeration.
public IEnumerator<ZipEntry> GetEnumerator()
Returns
- IEnumerator<ZipEntry>
A generic enumerator suitable for use within a foreach loop.
Examples
This example reads a zipfile of a given name, then enumerates the entries in that zip file, and displays the information about each entry on the Console.
using (ZipFile zip = ZipFile.Read(zipfile))
{
bool header = true;
foreach (ZipEntry e in zip)
{
if (header)
{
System.Console.WriteLine("Zipfile: {0}", zip.Name);
System.Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded);
System.Console.WriteLine("BitField: 0x{0:X2}", e.BitField);
System.Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod);
System.Console.WriteLine("\n{1,-22} {2,-6} {3,4} {4,-8} {0}",
"Filename", "Modified", "Size", "Ratio", "Packed");
System.Console.WriteLine(new System.String('-', 72));
header = false;
}
System.Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}",
e.FileName,
e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
e.UncompressedSize,
e.CompressionRatio,
e.CompressedSize);
e.Extract();
}
}
Dim ZipFileToExtract As String = "c:\foo.zip"
Using zip As ZipFile = ZipFile.Read(ZipFileToExtract)
Dim header As Boolean = True
Dim e As ZipEntry
For Each e In zip
If header Then
Console.WriteLine("Zipfile: {0}", zip.Name)
Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded)
Console.WriteLine("BitField: 0x{0:X2}", e.BitField)
Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod)
Console.WriteLine(ChrW(10) & "{1,-22} {2,-6} {3,4} {4,-8} {0}", _
"Filename", "Modified", "Size", "Ratio", "Packed" )
Console.WriteLine(New String("-"c, 72))
header = False
End If
Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", _
e.FileName, _
e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), _
e.UncompressedSize, _
e.CompressionRatio, _
e.CompressedSize )
e.Extract
Next
End Using
Remarks
You probably do not want to call GetEnumerator explicitly. Instead
it is implicitly called when you use a foreach loop in C#, or a
For Each loop in VB.NET.
GetNewEnum()
An IEnumerator, for use of a ZipFile in a foreach construct.
public IEnumerator GetNewEnum()
Returns
- IEnumerator
The IEnumerator over the entries in the ZipFile.
Remarks
This method is included for COM support. An application generally does not call
this method directly. It is called implicitly by COM clients when enumerating
the entries in the ZipFile instance. In VBScript, this is done with a For Each
statement. In Javascript, this is done with new Enumerator(zipfile).
Initialize(string)
Initialize a ZipFile instance by reading in a zip file.
public void Initialize(string fileName)
Parameters
fileNamestringthe name of the existing zip file to read in.
Remarks
This method is primarily useful from COM Automation environments, when
reading or extracting zip files. In COM, it is not possible to invoke
parameterized constructors for a class. A COM Automation application can
update a zip file by using the default (no argument)
constructor, then calling Initialize() to read the contents
of an on-disk zip archive into the ZipFile instance.
.NET applications are encouraged to use the ZipFile.Read() methods
for better clarity.
IsZipFile(Stream, bool)
Checks a stream to see if it contains a valid zip archive.
public static bool IsZipFile(Stream stream, bool testExtract)
Parameters
Returns
- bool
true if the stream contains a valid zip archive.
Remarks
This method reads the zip archive contained in the specified stream, verifying the ZIP metadata as it reads. If testExtract is true, this method also extracts each entry in the archive, dumping all the bits into Null.
If everything succeeds, then the method returns true. If anything fails - for example if an incorrect signature or CRC is found, indicating a corrupt file, the the method returns false. This method also returns false for a file that does not exist.
If testExtract is true, this method reads in the content for each
entry, expands it, and checks CRCs. This provides an additional check
beyond verifying the zip header data.
If testExtract is true, and if any of the zip entries are protected
with a password, this method will return false. If you want to verify a
ZipFile that has entries which are protected with a password, you will need
to do that manually.
- See Also
IsZipFile(string)
Checks the given file to see if it appears to be a valid zip file.
public static bool IsZipFile(string fileName)
Parameters
fileNamestringThe file to check.
Returns
- bool
true if the file appears to be a zip file.
Remarks
Calling this method is equivalent to calling IsZipFile(string, bool) with the testExtract parameter set to false.
IsZipFile(string, bool)
Checks a file to see if it is a valid zip file.
public static bool IsZipFile(string fileName, bool testExtract)
Parameters
fileNamestringThe zip file to check.
testExtractbooltrue if the caller wants to extract each entry.
Returns
- bool
true if the file contains a valid zip file.
Remarks
This method opens the specified zip file, reads in the zip archive, verifying the ZIP metadata as it reads.
If everything succeeds, then the method returns true. If anything fails - for example if an incorrect signature or CRC is found, indicating a corrupt file, the the method returns false. This method also returns false for a file that does not exist.
If testExtract is true, as part of its check, this
method reads in the content for each entry, expands it, and checks CRCs.
This provides an additional check beyond verifying the zip header and
directory data.
If testExtract is true, and if any of the zip entries
are protected with a password, this method will return false. If you want
to verify a ZipFile that has entries which are protected with a
password, you will need to do that manually.
Read(Stream)
Reads a zip archive from a stream.
public static ZipFile Read(Stream zipStream)
Parameters
zipStreamStreamthe stream containing the zip data.
Returns
- ZipFile
The ZipFile instance read from the stream
Examples
This example shows how to Read zip content from a stream, and extract one entry into a different stream. In this example, the filename "NameOfEntryInArchive.doc", refers only to the name of the entry within the zip archive. A file by that name is not created in the filesystem. The I/O is done strictly with the given streams.
using (ZipFile zip = ZipFile.Read(InputStream))
{
zip.Extract("NameOfEntryInArchive.doc", OutputStream);
}
Using zip as ZipFile = ZipFile.Read(InputStream)
zip.Extract("NameOfEntryInArchive.doc", OutputStream)
End Using
Remarks
When reading from a file, it's probably easier to just use ZipFile.Read(String, ReadOptions). This overload is useful when when the zip archive content is available from an already-open stream. The stream must be open and readable and seekable when calling this method. The stream is left open when the reading is completed.
Using this overload, the stream is read using the default
System.Text.Encoding, which is the IBM437
codepage. If you want to specify the encoding to use when
reading the zipfile content, see
ZipFile.Read(Stream, ReadOptions). This
Reading of zip content begins at the current position in the stream. This means if you have a stream that concatenates regular data and zip data, if you position the open, readable stream at the start of the zip data, you will be able to read the zip archive using this constructor, or any of the ZipFile constructors that accept a Stream as input. Some examples of where this might be useful: the zip content is concatenated at the end of a regular EXE file, as some self-extracting archives do. (Note: SFX files produced by DotNetZip do not work this way; they can be read as normal ZIP files). Another example might be a stream being read from a database, where the zip content is embedded within an aggregate stream of data.
Read(Stream, ReadOptions)
Reads a zip file archive from the given stream using the specified options.
public static ZipFile Read(Stream zipStream, ReadOptions options)
Parameters
zipStreamStreamthe stream containing the zip data.
optionsReadOptionsThe set of options to use when reading the zip file.
Returns
- ZipFile
The ZipFile instance read from the stream.
Remarks
When reading from a file, it's probably easier to just use ZipFile.Read(String, ReadOptions). This overload is useful when when the zip archive content is available from an already-open stream. The stream must be open and readable and seekable when calling this method. The stream is left open when the reading is completed.
Reading of zip content begins at the current position in the stream. This means if you have a stream that concatenates regular data and zip data, if you position the open, readable stream at the start of the zip data, you will be able to read the zip archive using this constructor, or any of the ZipFile constructors that accept a Stream as input. Some examples of where this might be useful: the zip content is concatenated at the end of a regular EXE file, as some self-extracting archives do. (Note: SFX files produced by DotNetZip do not work this way; they can be read as normal ZIP files). Another example might be a stream being read from a database, where the zip content is embedded within an aggregate stream of data.
Exceptions
- Exception
Thrown if the zip archive cannot be read.
- See Also
Read(string)
Reads a zip file archive and returns the instance.
public static ZipFile Read(string fileName)
Parameters
fileNamestringThe name of the zip archive to open. This can be a fully-qualified or relative pathname.
Returns
- ZipFile
The instance read from the zip archive.
Remarks
The stream is read using the default System.Text.Encoding, which is the
IBM437 codepage.
Exceptions
- Exception
Thrown if the
ZipFilecannot be read. The implementation of this method relies onSystem.IO.File.OpenRead, which can throw a variety of exceptions, including specific exceptions if a file is not found, an unauthorized access exception, exceptions for poorly formatted filenames, and so on.
- See Also
Read(string, ReadOptions)
Reads a zip file archive from the named filesystem file using the specified options.
public static ZipFile Read(string fileName, ReadOptions options)
Parameters
fileNamestringThe name of the zip archive to open. This can be a fully-qualified or relative pathname.
optionsReadOptionsThe set of options to use when reading the zip file.
Returns
- ZipFile
The ZipFile instance read from the zip archive.
Examples
This example shows how to read a zip file using the Big-5 Chinese code page (950), and extract each entry in the zip file, while sending status messages out to the Console.
For this code to work as intended, the zipfile must have been created using the big5 code page (CP950). This is typical, for example, when using WinRar on a machine with CP950 set as the default code page. In that case, the names of entries within the Zip archive will be stored in that code page, and reading the zip archive must be done using that code page. If the application did not use the correct code page in ZipFile.Read(), then names of entries within the zip archive would not be correctly retrieved.
string zipToExtract = "MyArchive.zip";
string extractDirectory = "extract";
var options = new ReadOptions
{
StatusMessageWriter = System.Console.Out,
Encoding = System.Text.Encoding.GetEncoding(950)
};
using (ZipFile zip = ZipFile.Read(zipToExtract, options))
{
foreach (ZipEntry e in zip)
{
e.Extract(extractDirectory);
}
}
Dim zipToExtract as String = "MyArchive.zip"
Dim extractDirectory as String = "extract"
Dim options as New ReadOptions
options.Encoding = System.Text.Encoding.GetEncoding(950)
options.StatusMessageWriter = System.Console.Out
Using zip As ZipFile = ZipFile.Read(zipToExtract, options)
Dim e As ZipEntry
For Each e In zip
e.Extract(extractDirectory)
Next
End Using
This example shows how to read a zip file using the default
code page, to remove entries that have a modified date before a given threshold,
sending status messages out to a StringWriter.
var options = new ReadOptions
{
StatusMessageWriter = new System.IO.StringWriter()
};
using (ZipFile zip = ZipFile.Read("PackedDocuments.zip", options))
{
var Threshold = new DateTime(2007,7,4);
// We cannot remove the entry from the list, within the context of
// an enumeration of said list.
// So we add the doomed entry to a list to be removed later.
// pass 1: mark the entries for removal
var MarkedEntries = new System.Collections.Generic.List<ZipEntry>();
foreach (ZipEntry e in zip)
{
if (e.LastModified < Threshold)
MarkedEntries.Add(e);
}
// pass 2: actually remove the entry.
foreach (ZipEntry zombie in MarkedEntries)
zip.RemoveEntry(zombie);
zip.Comment = "This archive has been updated.";
zip.Save();
}
// can now use contents of sw, eg store in an audit log
Dim options as New ReadOptions
options.StatusMessageWriter = New System.IO.StringWriter
Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip", options)
Dim Threshold As New DateTime(2007, 7, 4)
' We cannot remove the entry from the list, within the context of
' an enumeration of said list.
' So we add the doomed entry to a list to be removed later.
' pass 1: mark the entries for removal
Dim MarkedEntries As New System.Collections.Generic.List(Of ZipEntry)
Dim e As ZipEntry
For Each e In zip
If (e.LastModified < Threshold) Then
MarkedEntries.Add(e)
End If
Next
' pass 2: actually remove the entry.
Dim zombie As ZipEntry
For Each zombie In MarkedEntries
zip.RemoveEntry(zombie)
Next
zip.Comment = "This archive has been updated."
zip.Save
End Using
' can now use contents of sw, eg store in an audit log
Remarks
This version of the Read() method allows the caller to pass
in a TextWriter an Encoding, via an instance of the
ReadOptions class. The ZipFile is read in using the
specified encoding for entries where UTF-8 encoding is not
explicitly specified.
Exceptions
- Exception
Thrown if the zipfile cannot be read. The implementation of this method relies on
System.IO.File.OpenRead, which can throw a variety of exceptions, including specific exceptions if a file is not found, an unauthorized access exception, exceptions for poorly formatted filenames, and so on.
- See Also
RemoveEntries(ICollection<ZipEntry>)
This method removes a collection of entries from the ZipFile.
public void RemoveEntries(ICollection<ZipEntry> entriesToRemove)
Parameters
entriesToRemoveICollection<ZipEntry>A collection of ZipEntry instances from this zip file to be removed. For example, you can pass in an array of ZipEntry instances; or you can call SelectEntries(), and then add or remove entries from that ICollection<ZipEntry> (ICollection(Of ZipEntry) in VB), and pass that ICollection to this method.
- See Also
RemoveEntries(ICollection<string>)
This method removes a collection of entries from the ZipFile, by name.
public void RemoveEntries(ICollection<string> entriesToRemove)
Parameters
entriesToRemoveICollection<string>A collection of strings that refer to names of entries to be removed from the
ZipFile. For example, you can pass in an array or a List of Strings that provide the names of entries to be removed.
- See Also
RemoveEntry(ZipEntry)
Removes the given ZipEntry from the zip archive.
public void RemoveEntry(ZipEntry entry)
Parameters
entryZipEntryThe
ZipEntryto remove from the zip.
Examples
In this example, all entries in the zip archive dating from before December 31st, 2007, are removed from the archive. This is actually much easier if you use the RemoveSelectedEntries method. But I needed an example for RemoveEntry, so here it is.
String ZipFileToRead = "ArchiveToModify.zip";
System.DateTime Threshold = new System.DateTime(2007,12,31);
using (ZipFile zip = ZipFile.Read(ZipFileToRead))
{
var EntriesToRemove = new System.Collections.Generic.List<ZipEntry>();
foreach (ZipEntry e in zip)
{
if (e.LastModified < Threshold)
{
// We cannot remove the entry from the list, within the context of
// an enumeration of said list.
// So we add the doomed entry to a list to be removed later.
EntriesToRemove.Add(e);
}
}
// actually remove the doomed entries.
foreach (ZipEntry zombie in EntriesToRemove)
zip.RemoveEntry(zombie);
zip.Comment= String.Format("This zip archive was updated at {0}.",
System.DateTime.Now.ToString("G"));
// save with a different name
zip.Save("Archive-Updated.zip");
}
Dim ZipFileToRead As String = "ArchiveToModify.zip"
Dim Threshold As New DateTime(2007, 12, 31)
Using zip As ZipFile = ZipFile.Read(ZipFileToRead)
Dim EntriesToRemove As New System.Collections.Generic.List(Of ZipEntry)
Dim e As ZipEntry
For Each e In zip
If (e.LastModified < Threshold) Then
' We cannot remove the entry from the list, within the context of
' an enumeration of said list.
' So we add the doomed entry to a list to be removed later.
EntriesToRemove.Add(e)
End If
Next
' actually remove the doomed entries.
Dim zombie As ZipEntry
For Each zombie In EntriesToRemove
zip.RemoveEntry(zombie)
Next
zip.Comment = String.Format("This zip archive was updated at {0}.", DateTime.Now.ToString("G"))
'save as a different name
zip.Save("Archive-Updated.zip")
End Using
Remarks
After calling RemoveEntry, the application must call Save to
make the changes permanent.
Exceptions
- ArgumentException
Thrown if the specified
ZipEntrydoes not exist in theZipFile.
- See Also
RemoveEntry(string)
Removes the ZipEntry with the given filename from the zip archive.
public void RemoveEntry(string fileName)
Parameters
fileNamestringThe name of the file, including any directory path, to remove from the zip. The filename match is not case-sensitive by default; you can use the
CaseSensitiveRetrievalproperty to change this behavior. The pathname can use forward-slashes or backward slashes.
Examples
This example shows one way to remove an entry with a given filename from an existing zip archive.
String zipFileToRead= "PackedDocuments.zip";
string candidate = "DatedMaterial.xps";
using (ZipFile zip = ZipFile.Read(zipFileToRead))
{
if (zip.EntryFilenames.Contains(candidate))
{
zip.RemoveEntry(candidate);
zip.Comment= String.Format("The file '{0}' has been removed from this archive.",
Candidate);
zip.Save();
}
}
Dim zipFileToRead As String = "PackedDocuments.zip"
Dim candidate As String = "DatedMaterial.xps"
Using zip As ZipFile = ZipFile.Read(zipFileToRead)
If zip.EntryFilenames.Contains(candidate) Then
zip.RemoveEntry(candidate)
zip.Comment = String.Format("The file '{0}' has been removed from this archive.", Candidate)
zip.Save
End If
End Using
Remarks
After calling RemoveEntry, the application must call Save to
make the changes permanent.
Exceptions
- InvalidOperationException
Thrown if the
ZipFileis not updatable.- ArgumentException
Thrown if a
ZipEntrywith the specified filename does not exist in theZipFile.
RemoveSelectedEntries(string)
Remove entries from the zipfile by specified criteria.
public int RemoveSelectedEntries(string selectionCriteria)
Parameters
selectionCriteriastringthe string that specifies which entries to select
Returns
- int
the number of entries removed
Examples
This example removes all entries in a zip file that were modified prior to January 1st, 2008.
using (ZipFile zip1 = ZipFile.Read(ZipFileName))
{
// remove all entries from prior to Jan 1, 2008
zip1.RemoveEntries("mtime < 2008-01-01");
// don't forget to save the archive!
zip1.Save();
}
Using zip As ZipFile = ZipFile.Read(ZipFileName)
' remove all entries from prior to Jan 1, 2008
zip1.RemoveEntries("mtime < 2008-01-01")
' do not forget to save the archive!
zip1.Save
End Using
Remarks
This method allows callers to remove the collection of entries from the zipfile that fit the specified criteria. The criteria are described in a string format, and can include patterns for the filename; constraints on the size of the entry; constraints on the last modified, created, or last accessed time for the file described by the entry; or the attributes of the entry.
For details on the syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
This method is intended for use with a ZipFile that has been read from storage. When creating a new ZipFile, this method will work only after the ZipArchive has been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip archive from storage.) Calling SelectEntries on a ZipFile that has not yet been saved will deliver undefined results.
Exceptions
- Exception
Thrown if selectionCriteria has an invalid syntax.
RemoveSelectedEntries(string, string)
Remove entries from the zipfile by specified criteria, and within the specified path in the archive.
public int RemoveSelectedEntries(string selectionCriteria, string directoryPathInArchive)
Parameters
selectionCriteriastringthe string that specifies which entries to select
directoryPathInArchivestringthe directory in the archive from which to select entries. If null, then all directories in the archive are used.
Returns
- int
the number of entries removed
Examples
using (ZipFile zip1 = ZipFile.Read(ZipFileName))
{
// remove all entries from prior to Jan 1, 2008
zip1.RemoveEntries("mtime < 2008-01-01", "documents");
// a call to ZipFile.Save will make the modifications permanent
zip1.Save();
}
Using zip As ZipFile = ZipFile.Read(ZipFileName)
' remove all entries from prior to Jan 1, 2008
zip1.RemoveEntries("mtime < 2008-01-01", "documents")
' a call to ZipFile.Save will make the modifications permanent
zip1.Save
End Using
Remarks
This method allows callers to remove the collection of entries from the zipfile that fit the specified criteria. The criteria are described in a string format, and can include patterns for the filename; constraints on the size of the entry; constraints on the last modified, created, or last accessed time for the file described by the entry; or the attributes of the entry.
For details on the syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
This method is intended for use with a ZipFile that has been read from storage. When creating a new ZipFile, this method will work only after the ZipArchive has been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip archive from storage.) Calling SelectEntries on a ZipFile that has not yet been saved will deliver undefined results.
Exceptions
- Exception
Thrown if selectionCriteria has an invalid syntax.
Save()
Saves the Zip archive to argument file, specified by the Name property of the
ZipFile.
public void Save()
Remarks
The ZipFile instance is written to storage, typically argument zip file
in argument filesystem, only when the caller calls Save. In the typical
case, the Save operation writes the zip content to argument temporary file, and
then renames the temporary file to the desired name. If necessary, this
method will delete argument pre-existing file before the rename.
The Name property is specified either explicitly,
or implicitly using one of the parameterized ZipFile constructors. For
COM Automation clients, the Name property must be set explicitly,
because COM Automation clients cannot call parameterized constructors.
When using argument filesystem file for the Zip output, it is possible to call
Save multiple times on the ZipFile instance. With each
call the zip content is re-written to the same output file.
Data for entries that have been added to the ZipFile instance is
written to the output when the Save method is called. This means
that the input streams for those entries must be available at the time
the application calls Save. If, for example, the application
adds entries with AddEntry using argument dynamically-allocated
MemoryStream, the memory stream must not have been disposed
before the call to Save. See the InputStream property for more discussion of the
availability requirements of the input stream for an entry, and an
approach for providing just-in-time stream lifecycle management.
Exceptions
- BadStateException
Thrown if you haven't specified argument location or stream for saving the zip, either in the constructor or by setting the Name property, or if you try to save argument regular zip archive to argument filename with argument .exe extension.
- OverflowException
Thrown if MaxOutputSegmentSize or MaxOutputSegmentSize64 is non-zero, and the number of segments that would be generated for the spanned zip file during the save operation exceeds 99. If this happens, you need to increase the segment size.
- See Also
Save(Stream)
Save the zip archive to the specified stream.
public void Save(Stream outputStream)
Parameters
outputStreamStreamThe
System.IO.Streamto write to. It must be writable. If you created the ZipFile instance by calling ZipFile.Read(), this stream must not be the same stream you passed to ZipFile.Read().
Examples
This example saves the zipfile content into argument MemoryStream, and then gets the array of bytes from that MemoryStream.
using (var zip = new Ionic.Zip.ZipFile())
{
zip.CompressionLevel= CompressionLevel.BestCompression;
zip.Password = "VerySecret.";
zip.Encryption = EncryptionAlgorithm.WinZipAes128;
zip.AddFile(sourceFileName);
MemoryStream output = new MemoryStream();
zip.Save(output);
byte[] zipbytes = output.ToArray();
}
This example shows argument pitfall you should avoid. DO NOT read from argument stream, then try to save to the same stream. DO NOT DO THIS:
using (var fs = new FileStream(filename, FileMode.Open))
{
using (var zip = Ionic.Zip.ZipFile.Read(inputStream))
{
zip.AddEntry("Name1.txt", "this is the content");
zip.Save(inputStream); // NO NO NO!!
}
}
Better like this:
using (var zip = Ionic.Zip.ZipFile.Read(filename))
{
zip.AddEntry("Name1.txt", "this is the content");
zip.Save(); // YES!
}
Remarks
The ZipFile instance is written to storage - typically argument zip file
in argument filesystem, but using this overload, the storage can be anything
accessible via argument writable stream - only when the caller calls Save.
Use this method to save the zip content to argument stream directly. argument common
scenario is an ASP.NET application that dynamically generates argument zip file
and allows the browser to download it. The application can call
Save(Response.OutputStream) to write argument zipfile directly to the
output stream, without creating argument zip file on the disk on the ASP.NET
server.
Be careful when saving argument file to argument non-seekable stream, including
Response.OutputStream. When DotNetZip writes to argument non-seekable
stream, the zip archive is formatted in such argument way that may not be
compatible with all zip tools on all platforms. It's argument perfectly legal
and compliant zip file, but some people have reported problems opening
files produced this way using the Mac OS archive utility.
Save(string)
Save the file to argument new zipfile, with the given name.
public void Save(string fileName)
Parameters
fileNamestringThe name of the zip archive to save to. Existing files will be overwritten with great prejudice.
Examples
This example shows how to create and Save argument zip file.
using (ZipFile zip = new ZipFile())
{
zip.AddDirectory(@"c:\reports\January");
zip.Save("January.zip");
}
Using zip As New ZipFile()
zip.AddDirectory("c:\reports\January")
zip.Save("January.zip")
End Using
This example shows how to update argument zip file.
using (ZipFile zip = ZipFile.Read("ExistingArchive.zip"))
{
zip.AddFile("NewData.csv");
zip.Save("UpdatedArchive.zip");
}
Using zip As ZipFile = ZipFile.Read("ExistingArchive.zip")
zip.AddFile("NewData.csv")
zip.Save("UpdatedArchive.zip")
End Using
Remarks
This method allows the application to explicitly specify the name of the zip file when saving. Use this when creating argument new zip file, or when updating argument zip archive.
An application can also save argument zip archive in several places by calling this method multiple times in succession, with different filenames.
The ZipFile instance is written to storage, typically argument zip file in argument
filesystem, only when the caller calls Save. The Save operation writes
the zip content to argument temporary file, and then renames the temporary file
to the desired name. If necessary, this method will delete argument pre-existing file
before the rename.
Exceptions
- ArgumentException
Thrown if you specify argument directory for the filename.
SelectEntries(string)
Retrieve entries from the zipfile by specified criteria.
public ICollection<ZipEntry> SelectEntries(string selectionCriteria)
Parameters
selectionCriteriastringthe string that specifies which entries to select
Returns
- ICollection<ZipEntry>
a collection of ZipEntry objects that conform to the inclusion spec
Examples
This example selects all the PhotoShop files from within an archive, and extracts them to the current working directory.
using (ZipFile zip1 = ZipFile.Read(ZipFileName))
{
var PhotoShopFiles = zip1.SelectEntries("*.psd");
foreach (ZipEntry psd in PhotoShopFiles)
{
psd.Extract();
}
}
Using zip1 As ZipFile = ZipFile.Read(ZipFileName)
Dim PhotoShopFiles as ICollection(Of ZipEntry)
PhotoShopFiles = zip1.SelectEntries("*.psd")
Dim psd As ZipEntry
For Each psd In PhotoShopFiles
psd.Extract
Next
End Using
Remarks
This method allows callers to retrieve the collection of entries from the zipfile that fit the specified criteria. The criteria are described in a string format, and can include patterns for the filename; constraints on the size of the entry; constraints on the last modified, created, or last accessed time for the file described by the entry; or the attributes of the entry.
For details on the syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
This method is intended for use with a ZipFile that has been read from storage. When creating a new ZipFile, this method will work only after the ZipArchive has been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip archive from storage.) Calling SelectEntries on a ZipFile that has not yet been saved will deliver undefined results.
Exceptions
- Exception
Thrown if selectionCriteria has an invalid syntax.
SelectEntries(string, string)
Retrieve entries from the zipfile by specified criteria.
public ICollection<ZipEntry> SelectEntries(string selectionCriteria, string directoryPathInArchive)
Parameters
selectionCriteriastringthe string that specifies which entries to select
directoryPathInArchivestringthe directory in the archive from which to select entries. If null, then all directories in the archive are used.
Returns
- ICollection<ZipEntry>
a collection of ZipEntry objects that conform to the inclusion spec
Examples
using (ZipFile zip1 = ZipFile.Read(ZipFileName))
{
var UpdatedPhotoShopFiles = zip1.SelectEntries("*.psd", "UpdatedFiles");
foreach (ZipEntry e in UpdatedPhotoShopFiles)
{
// prompt for extract here
if (WantExtract(e.FileName))
e.Extract();
}
}
Using zip1 As ZipFile = ZipFile.Read(ZipFileName)
Dim UpdatedPhotoShopFiles As ICollection(Of ZipEntry) = zip1.SelectEntries("*.psd", "UpdatedFiles")
Dim e As ZipEntry
For Each e In UpdatedPhotoShopFiles
' prompt for extract here
If Me.WantExtract(e.FileName) Then
e.Extract
End If
Next
End Using
Remarks
This method allows callers to retrieve the collection of entries from the zipfile that fit the specified criteria. The criteria are described in a string format, and can include patterns for the filename; constraints on the size of the entry; constraints on the last modified, created, or last accessed time for the file described by the entry; or the attributes of the entry.
For details on the syntax for the selectionCriteria parameter, see AddSelectedFiles(string).
This method is intended for use with a ZipFile that has been read from storage. When creating a new ZipFile, this method will work only after the ZipArchive has been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip archive from storage.) Calling SelectEntries on a ZipFile that has not yet been saved will deliver undefined results.
Exceptions
- Exception
Thrown if selectionCriteria has an invalid syntax.
ToString()
Provides a string representation of the instance.
public override string ToString()
Returns
- string
a string representation of the instance.
UpdateDirectory(string)
Add or update a directory in a zip archive.
public ZipEntry UpdateDirectory(string directoryName)
Parameters
directoryNamestringThe path to the directory to be added to the zip archive, or updated in the zip archive.
Returns
- ZipEntry
The
ZipEntrycorresponding to the Directory that was added or updated.
Remarks
If the specified directory does not exist in the archive, then this method
is equivalent to calling AddDirectory(). If the specified
directory already exists in the archive, then this method updates any
existing entries, and adds any new entries. Any entries that are in the
zip archive but not in the specified directory, are left alone. In other
words, the contents of the zip file will be a union of the previous
contents and the new files.
- See Also
UpdateDirectory(string, string)
Add or update a directory in the zip archive at the specified root directory in the archive.
public ZipEntry UpdateDirectory(string directoryName, string directoryPathInArchive)
Parameters
directoryNamestringThe path to the directory to be added to the zip archive, or updated in the zip archive.
directoryPathInArchivestringSpecifies a directory path to use to override any path in the
directoryName. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passingnull(Nothingin VB) will use the path on thedirectoryName, if any. Passing the empty string ("") will insert the item at the root path within the archive.
Returns
- ZipEntry
The
ZipEntrycorresponding to the Directory that was added or updated.
Remarks
If the specified directory does not exist in the archive, then this method
is equivalent to calling AddDirectory(). If the specified
directory already exists in the archive, then this method updates any
existing entries, and adds any new entries. Any entries that are in the
zip archive but not in the specified directory, are left alone. In other
words, the contents of the zip file will be a union of the previous
contents and the new files.
- See Also
UpdateEntry(string, OpenDelegate, CloseDelegate)
Updates the given entry in the ZipFile, using the given delegates
to open and close the stream that provides the content for the ZipEntry.
public ZipEntry UpdateEntry(string entryName, OpenDelegate opener, CloseDelegate closer)
Parameters
entryNamestringThe name, including any path, to use within the archive for the entry.
openerOpenDelegatethe delegate that will be invoked to open the stream
closerCloseDelegatethe delegate that will be invoked to close the stream
Returns
- ZipEntry
The
ZipEntryadded or updated.
Remarks
Calling this method is equivalent to removing the ZipEntry for the
given file name and directory path, if it exists, and then calling AddEntry(string, OpenDelegate, CloseDelegate). See the
documentation for that method for further explanation.
UpdateEntry(string, WriteDelegate)
Updates the given entry in the ZipFile, using the given delegate
as the source for content for the ZipEntry.
public ZipEntry UpdateEntry(string entryName, WriteDelegate writer)
Parameters
entryNamestringThe name, including any path, to use within the archive for the entry.
writerWriteDelegatethe delegate which will write the entry content.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
Calling this method is equivalent to removing the ZipEntry for the
given file name and directory path, if it exists, and then calling AddEntry(string, WriteDelegate). See the
documentation for that method for further explanation.
UpdateEntry(string, byte[])
Updates the given entry in the ZipFile, using the given byte
array as content for the entry.
public ZipEntry UpdateEntry(string entryName, byte[] byteContent)
Parameters
entryNamestringThe name, including any path, to use within the archive for the entry.
byteContentbyte[]The content to use for the
ZipEntry.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
Calling this method is equivalent to removing the ZipEntry
for the given filename and directory path, if it exists, and then
calling AddEntry(string, byte[]). See the
documentation for that method for further explanation.
UpdateEntry(string, Stream)
Updates the given entry in the ZipFile, using the given stream as
input, and the given filename and given directory Path.
public ZipEntry UpdateEntry(string entryName, Stream stream)
Parameters
entryNamestringThe name, including any path, to use within the archive for the entry.
streamStreamThe input stream from which to read file data.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
Calling the method is equivalent to calling RemoveEntry() if an
entry by the same name already exists, and then calling AddEntry()
with the given fileName and stream.
The stream must be open and readable during the call to
ZipFile.Save. You can dispense the stream on a just-in-time basis
using the InputStream property. Check the
documentation of that property for more information.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
UpdateEntry(string, string)
Updates the given entry in the ZipFile, using the given
string as content for the ZipEntry.
public ZipEntry UpdateEntry(string entryName, string content)
Parameters
entryNamestringThe name, including any path, to use within the archive for the entry.
contentstringThe content of the file, should it be extracted from the zip.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
Calling this method is equivalent to removing the ZipEntry for
the given file name and directory path, if it exists, and then calling
AddEntry(string, string). See the documentation for
that method for further explanation. The string content is encoded
using the default encoding for the machine. This encoding is distinct
from the encoding used for the filename itself. See
AlternateEncoding.
UpdateEntry(string, string, Encoding)
Updates the given entry in the ZipFile, using the given string as
content for the ZipEntry.
public ZipEntry UpdateEntry(string entryName, string content, Encoding encoding)
Parameters
entryNamestringThe name, including any path, to use within the archive for the entry.
contentstringThe content of the file, should it be extracted from the zip.
encodingEncodingThe text encoding to use when encoding the string. Be aware: This is distinct from the text encoding used to encode the filename. See AlternateEncoding.
Returns
- ZipEntry
The
ZipEntryadded.
Remarks
Calling this method is equivalent to removing the ZipEntry for the
given file name and directory path, if it exists, and then calling AddEntry(string, string, Encoding). See the
documentation for that method for further explanation.
UpdateFile(string)
Adds or Updates a File in a Zip file archive.
public ZipEntry UpdateFile(string fileName)
Parameters
fileNamestringThe name of the file to add or update. It should refer to a file in the filesystem. The name of the file may be a relative path or a fully-qualified path.
Returns
- ZipEntry
The
ZipEntrycorresponding to the File that was added or updated.
Examples
This example shows how to Update an existing entry in a zipfile. The first call to UpdateFile adds the file to the newly-created zip archive. The second call to UpdateFile updates the content for that file in the zip archive.
using (ZipFile zip1 = new ZipFile())
{
// UpdateFile might more accurately be called "AddOrUpdateFile"
zip1.UpdateFile("MyDocuments\\Readme.txt");
zip1.UpdateFile("CustomerList.csv");
zip1.Comment = "This zip archive has been created.";
zip1.Save("Content.zip");
}
using (ZipFile zip2 = ZipFile.Read("Content.zip"))
{
zip2.UpdateFile("Updates\\Readme.txt");
zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed.";
zip2.Save();
}
Using zip1 As New ZipFile
' UpdateFile might more accurately be called "AddOrUpdateFile"
zip1.UpdateFile("MyDocuments\Readme.txt")
zip1.UpdateFile("CustomerList.csv")
zip1.Comment = "This zip archive has been created."
zip1.Save("Content.zip")
End Using
Using zip2 As ZipFile = ZipFile.Read("Content.zip")
zip2.UpdateFile("Updates\Readme.txt")
zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed."
zip2.Save
End Using
Remarks
This method adds a file to a zip archive, or, if the file already exists
in the zip archive, this method Updates the content of that given filename
in the zip archive. The UpdateFile method might more accurately be
called "AddOrUpdateFile".
Upon success, there is no way for the application to learn whether the file was added versus updated.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
UpdateFile(string, string)
Adds or Updates a File in a Zip file archive.
public ZipEntry UpdateFile(string fileName, string directoryPathInArchive)
Parameters
fileNamestringThe name of the file to add or update. It should refer to a file in the filesystem. The name of the file may be a relative path or a fully-qualified path.
directoryPathInArchivestringSpecifies a directory path to use to override any path in the
fileName. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passingnull(Nothingin VB) will use the path on thefileName, if any. Passing the empty string ("") will insert the item at the root path within the archive.
Returns
- ZipEntry
The
ZipEntrycorresponding to the File that was added or updated.
Remarks
This method adds a file to a zip archive, or, if the file already exists in the zip archive, this method Updates the content of that given filename in the zip archive.
This version of the method allows the caller to explicitly specify the directory path to be used in the archive. The entry to be added or updated is found by using the specified directory path, combined with the basename of the specified filename.
Upon success, there is no way for the application to learn if the file was added versus updated.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
UpdateFiles(IEnumerable<string>)
Adds or updates a set of files in the ZipFile.
public void UpdateFiles(IEnumerable<string> fileNames)
Parameters
fileNamesIEnumerable<string>The collection of names of the files to update. Each string should refer to a file in the filesystem. The name of the file may be a relative path or a fully-qualified path.
Remarks
Any files that already exist in the archive are updated. Any files that don't yet exist in the archive are added.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to each
ZipEntry added.
UpdateFiles(IEnumerable<string>, string)
Adds or updates a set of files to the ZipFile, using the specified
directory path in the archive.
public void UpdateFiles(IEnumerable<string> fileNames, string directoryPathInArchive)
Parameters
fileNamesIEnumerable<string>The names of the files to add or update. Each string should refer to a file in the filesystem. The name of the file may be a relative path or a fully-qualified path.
directoryPathInArchivestringSpecifies a directory path to use to override any path in the file name. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passing
null(Nothingin VB) will use the path on each of thefileNames, if any. Passing the empty string ("") will insert the item at the root path within the archive.
Remarks
Any files that already exist in the archive are updated. Any files that don't yet exist in the archive are added.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to each
ZipEntry added.
- See Also
UpdateItem(string)
Add or update a file or directory in the zip archive.
public void UpdateItem(string itemName)
Parameters
itemNamestringthe path to the file or directory to be added or updated.
Remarks
This is useful when the application is not sure or does not care if the
item to be added is a file or directory, and does not know or does not
care if the item already exists in the ZipFile. Calling this method
is equivalent to calling RemoveEntry() if an entry by the same name
already exists, followed calling by AddItem().
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
UpdateItem(string, string)
Add or update a file or directory.
public void UpdateItem(string itemName, string directoryPathInArchive)
Parameters
itemNamestringThe path for the File or Directory to be added or updated.
directoryPathInArchivestringSpecifies a directory path to use to override any path in the
itemName. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passingnull(Nothingin VB) will use the path on theitemName, if any. Passing the empty string ("") will insert the item at the root path within the archive.
Remarks
This method is useful when the application is not sure or does not care if
the item to be added is a file or directory, and does not know or does not
care if the item already exists in the ZipFile. Calling this method
is equivalent to calling RemoveEntry(), if an entry by that name
exists, and then calling AddItem().
This version of the method allows the caller to explicitly specify the
directory path to be used for the item being added to the archive. The
entry or entries that are added or updated will use the specified
DirectoryPathInArchive. Extracting the entry from the archive will
result in a file stored in that directory path.
For ZipFile properties including Encryption, Password, SetCompression, ProvisionalAlternateEncoding, ExtractExistingFile,
ZipErrorAction, and CompressionLevel, their
respective values at the time of this call will be applied to the
ZipEntry added.
- See Also
UpdateSelectedFiles(string, string, string, bool)
Updates the ZipFile with a selection of files from the disk that conform to the specified criteria.
public void UpdateSelectedFiles(string selectionCriteria, string directoryOnDisk, string directoryPathInArchive, bool recurseDirectories)
Parameters
selectionCriteriastringThe criteria for selection of files to add to the
ZipFile.directoryOnDiskstringThe path to the directory in the filesystem from which to select files.
directoryPathInArchivestringSpecifies a directory path to use to in place of the
directoryOnDisk. This path may, or may not, correspond to a real directory in the current filesystem. If the files within the zip are later extracted, this is the path used for the extracted file. Passing null (nothing in VB) will use the path on the file name, if any; in other words it would usedirectoryOnDisk, plus any subdirectory. Passing the empty string ("") will insert the item at the root path within the archive.recurseDirectoriesboolIf true, the method also scans subdirectories for files matching the criteria.
Remarks
This method selects files from the specified disk directory that match the
specified selection criteria, and Updates the ZipFile with those
files, using the specified directory path in the archive. If
recurseDirectories is true, files are also selected from
subdirectories, and the directory structure in the filesystem is
reproduced in the zip archive, rooted at the directory specified by
directoryOnDisk. For details on the syntax for the
selectionCriteria parameter, see AddSelectedFiles(string).
- See Also
Events
AddProgress
An event handler invoked before, during, and after Adding entries to a zip archive.
public event EventHandler<AddProgressEventArgs> AddProgress
Event Type
Examples
int _numEntriesToAdd= 0;
int _numEntriesAdded= 0;
void AddProgressHandler(object sender, AddProgressEventArgs element)
{
switch (element.EventType)
{
case ZipProgressEventType.Adding_Started:
Console.WriteLine("Adding files to the zip...");
break;
case ZipProgressEventType.Adding_AfterAddEntry:
_numEntriesAdded++;
Console.WriteLine(String.Format("Adding file {0}/{1} :: {2}",
_numEntriesAdded, _numEntriesToAdd, element.CurrentEntry.FileName));
break;
case ZipProgressEventType.Adding_Completed:
Console.WriteLine("Added all files");
break;
}
}
void CreateTheZip()
{
using (ZipFile zip = new ZipFile())
{
zip.AddProgress += AddProgressHandler;
zip.AddDirectory(System.IO.Path.GetFileName(DirToZip));
zip.Save(ZipFileToCreate);
}
}
Private Sub AddProgressHandler(ByVal sender As Object, ByVal element As AddProgressEventArgs)
Select Case element.EventType
Case ZipProgressEventType.Adding_Started
Console.WriteLine("Adding files to the zip...")
Exit Select
Case ZipProgressEventType.Adding_AfterAddEntry
Console.WriteLine(String.Format("Adding file {0}", element.CurrentEntry.FileName))
Exit Select
Case ZipProgressEventType.Adding_Completed
Console.WriteLine("Added all files")
Exit Select
End Select
End Sub
Sub CreateTheZip()
Using zip as ZipFile = New ZipFile
AddHandler zip.AddProgress, AddressOf AddProgressHandler
zip.AddDirectory(System.IO.Path.GetFileName(DirToZip))
zip.Save(ZipFileToCreate);
End Using
End Sub
Remarks
Adding a large number of entries to a zip file can take a long time. For example, when calling AddDirectory(string) on a directory that contains 50,000 files, it could take 3 minutes or so. This event handler allws an application to track the progress of the Add operation, and to optionally cancel a lengthy Add operation.
- See Also
ExtractProgress
An event handler invoked before, during, and after extraction of entries in the zip archive.
public event EventHandler<ExtractProgressEventArgs> ExtractProgress
Event Type
Examples
private static bool justHadByteUpdate = false;
public static void ExtractProgress(object sender, ExtractProgressEventArgs element)
{
if(element.EventType == ZipProgressEventType.Extracting_EntryBytesWritten)
{
if (justHadByteUpdate)
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(" {0}/{1} ({2:N0}%)", element.BytesTransferred, element.TotalBytesToTransfer,
element.BytesTransferred / (0.01 * element.TotalBytesToTransfer ));
justHadByteUpdate = true;
}
else if(element.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry)
{
if (justHadByteUpdate)
Console.WriteLine();
Console.WriteLine("Extracting: {0}", element.CurrentEntry.FileName);
justHadByteUpdate= false;
}
}
public static ExtractZip(string zipToExtract, string directory)
{
string TargetDirectory= "extract";
using (var zip = ZipFile.Read(zipToExtract)) {
zip.ExtractProgress += ExtractProgress;
foreach (var element in zip1)
{
element.Extract(TargetDirectory, true);
}
}
}
Public Shared Sub Main(ByVal args As String())
Dim ZipToUnpack As String = "C1P3SML.zip"
Dim TargetDir As String = "ExtractTest_Extract"
Console.WriteLine("Extracting file {0} to {1}", ZipToUnpack, TargetDir)
Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack)
AddHandler zip1.ExtractProgress, AddressOf MyExtractProgress
Dim element As ZipEntry
For Each element In zip1
element.Extract(TargetDir, True)
Next
End Using
End Sub
Private Shared justHadByteUpdate As Boolean = False
Public Shared Sub MyExtractProgress(ByVal sender As Object, ByVal element As ExtractProgressEventArgs)
If (element.EventType = ZipProgressEventType.Extracting_EntryBytesWritten) Then
If ExtractTest.justHadByteUpdate Then
Console.SetCursorPosition(0, Console.CursorTop)
End If
Console.Write(" {0}/{1} ({2:N0}%)", element.BytesTransferred, element.TotalBytesToTransfer, (CDbl(element.BytesTransferred) / (0.01 * element.TotalBytesToTransfer)))
ExtractTest.justHadByteUpdate = True
ElseIf (element.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry) Then
If ExtractTest.justHadByteUpdate Then
Console.WriteLine
End If
Console.WriteLine("Extracting: {0}", element.CurrentEntry.FileName)
ExtractTest.justHadByteUpdate = False
End If
End Sub
Remarks
Depending on the particular event, different properties on the ExtractProgressEventArgs parameter are set. The following
table summarizes the available EventTypes and the conditions under
which this event handler is invoked with a
ExtractProgressEventArgs with the given EventType.
| value of EntryType | Meaning and conditions |
|---|---|
| ZipProgressEventType.Extracting_BeforeExtractAll | Set when ExtractAll() begins. The ArchiveName, Overwrite, and ExtractLocation properties are meaningful. |
| ZipProgressEventType.Extracting_AfterExtractAll | Set when ExtractAll() has completed. The ArchiveName, Overwrite, and ExtractLocation properties are meaningful. |
| ZipProgressEventType.Extracting_BeforeExtractEntry | Set when an Extract() on an entry in the ZipFile has begun. Properties that are meaningful: ArchiveName, EntriesTotal, CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. |
| ZipProgressEventType.Extracting_AfterExtractEntry | Set when an Extract() on an entry in the ZipFile has completed. Properties that are meaningful: ArchiveName, EntriesTotal, CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. |
| ZipProgressEventType.Extracting_EntryBytesWritten | Set within a call to Extract() on an entry in the ZipFile, as data is extracted for the entry. Properties that are meaningful: ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. |
| ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite |
Set within a call to Extract() on an entry in the ZipFile, when the
extraction would overwrite an existing file. This event type is used
only when ExtractExistingFileAction on the ZipFile or
ZipEntry is set to InvokeExtractProgressEvent.
|
- See Also
ReadProgress
An event handler invoked before, during, and after the reading of a zip archive.
public event EventHandler<ReadProgressEventArgs> ReadProgress
Event Type
Remarks
Depending on the particular event being signaled, different properties on the
ReadProgressEventArgs parameter are set. The following table
summarizes the available EventTypes and the conditions under which this
event handler is invoked with a ReadProgressEventArgs with the given EventType.
| value of EntryType | Meaning and conditions |
|---|---|
| ZipProgressEventType.Reading_Started | Fired just as ZipFile.Read() begins. Meaningful properties: ArchiveName. |
| ZipProgressEventType.Reading_Completed | Fired when ZipFile.Read() has completed. Meaningful properties: ArchiveName. |
| ZipProgressEventType.Reading_ArchiveBytesRead | Fired while reading, updates the number of bytes read for the entire archive. Meaningful properties: ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. |
| ZipProgressEventType.Reading_BeforeReadEntry | Indicates an entry is about to be read from the archive. Meaningful properties: ArchiveName, EntriesTotal. |
| ZipProgressEventType.Reading_AfterReadEntry | Indicates an entry has just been read from the archive. Meaningful properties: ArchiveName, EntriesTotal, CurrentEntry. |
- See Also
SaveProgress
An event handler invoked when a Save() starts, before and after each entry has been written to the archive, when a Save() completes, and during other Save events.
public event EventHandler<SaveProgressEventArgs> SaveProgress
Event Type
Examples
This example uses an anonymous method to handle the SaveProgress event, by updating a progress bar.
progressBar1.Value = 0;
progressBar1.Max = listbox1.Items.Count;
using (ZipFile zip = new ZipFile())
{
// listbox1 contains a list of filenames
zip.AddFiles(listbox1.Items);
// do the progress bar:
zip.SaveProgress += (sender, element) => {
if (element.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) {
progressBar1.PerformStep();
}
};
zip.Save(fs);
}
This example uses a named method as the
SaveProgress event handler, to update the user, in a
console-based application.
static bool justHadByteUpdate= false;
public static void SaveProgress(object sender, SaveProgressEventArgs element)
{
if (element.EventType == ZipProgressEventType.Saving_Started)
Console.WriteLine("Saving: {0}", element.ArchiveName);
else if (element.EventType == ZipProgressEventType.Saving_Completed)
{
justHadByteUpdate= false;
Console.WriteLine();
Console.WriteLine("Done: {0}", element.ArchiveName);
}
else if (element.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)
{
if (justHadByteUpdate)
Console.WriteLine();
Console.WriteLine(" Writing: {0} ({1}/{2})",
element.CurrentEntry.FileName, element.EntriesSaved, element.EntriesTotal);
justHadByteUpdate= false;
}
else if (element.EventType == ZipProgressEventType.Saving_EntryBytesRead)
{
if (justHadByteUpdate)
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(" {0}/{1} ({2:N0}%)", element.BytesTransferred, element.TotalBytesToTransfer,
element.BytesTransferred / (0.01 * element.TotalBytesToTransfer ));
justHadByteUpdate= true;
}
}
public static ZipUp(string targetZip, string directory)
{
using (var zip = new ZipFile()) {
zip.SaveProgress += SaveProgress;
zip.AddDirectory(directory);
zip.Save(targetZip);
}
}
Public Sub ZipUp(ByVal targetZip As String, ByVal directory As String)
Using zip As ZipFile = New ZipFile
AddHandler zip.SaveProgress, AddressOf MySaveProgress
zip.AddDirectory(directory)
zip.Save(targetZip)
End Using
End Sub
Private Shared justHadByteUpdate As Boolean = False
Public Shared Sub MySaveProgress(ByVal sender As Object, ByVal element As SaveProgressEventArgs)
If (element.EventType Is ZipProgressEventType.Saving_Started) Then
Console.WriteLine("Saving: {0}", element.ArchiveName)
ElseIf (element.EventType Is ZipProgressEventType.Saving_Completed) Then
justHadByteUpdate = False
Console.WriteLine
Console.WriteLine("Done: {0}", element.ArchiveName)
ElseIf (element.EventType Is ZipProgressEventType.Saving_BeforeWriteEntry) Then
If justHadByteUpdate Then
Console.WriteLine
End If
Console.WriteLine(" Writing: {0} ({1}/{2})", element.CurrentEntry.FileName, element.EntriesSaved, element.EntriesTotal)
justHadByteUpdate = False
ElseIf (element.EventType Is ZipProgressEventType.Saving_EntryBytesRead) Then
If justHadByteUpdate Then
Console.SetCursorPosition(0, Console.CursorTop)
End If
Console.Write(" {0}/{1} ({2:N0}%)", element.BytesTransferred, _
element.TotalBytesToTransfer, _
(CDbl(element.BytesTransferred) / (0.01 * element.TotalBytesToTransfer)))
justHadByteUpdate = True
End If
End Sub
This is a more complete example of using the SaveProgress events in a Windows Forms application, with a Thread object.
delegate void SaveEntryProgress(SaveProgressEventArgs element);
delegate void ButtonClick(object sender, EventArgs element);
public class WorkerOptions
{
public string ZipName;
public string Folder;
public string Encoding;
public string Comment;
public int ZipFlavor;
public Zip64Option Zip64;
}
private int _progress2MaxFactor;
private bool _saveCanceled;
private long _totalBytesBeforeCompress;
private long _totalBytesAfterCompress;
private Thread _workerThread;
private void btnZipup_Click(object sender, EventArgs element)
{
KickoffZipup();
}
private void btnCancel_Click(object sender, EventArgs element)
{
if (this.lblStatus.InvokeRequired)
{
this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, element });
}
else
{
_saveCanceled = true;
lblStatus.Text = "Canceled...";
ResetState();
}
}
private void KickoffZipup()
{
_folderName = tbDirName.Text;
if (_folderName == null || _folderName == "") return;
if (this.tbZipName.Text == null || this.tbZipName.Text == "") return;
// check for existence of the zip file:
if (System.IO.File.Exists(this.tbZipName.Text))
{
var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) already exists." +
" Do you want to overwrite this file?", this.tbZipName.Text),
"Confirmation is Required", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dlgResult != DialogResult.Yes) return;
System.IO.File.Delete(this.tbZipName.Text);
}
_saveCanceled = false;
_nFilesCompleted = 0;
_totalBytesAfterCompress = 0;
_totalBytesBeforeCompress = 0;
this.btnOk.Enabled = false;
this.btnOk.Text = "Zipping...";
this.btnCancel.Enabled = true;
lblStatus.Text = "Zipping...";
var options = new WorkerOptions
{
ZipName = this.tbZipName.Text,
Folder = _folderName,
Encoding = "ibm437"
};
if (this.comboBox1.SelectedIndex != 0)
{
options.Encoding = this.comboBox1.SelectedItem.ToString();
}
if (this.radioFlavorSfxCmd.Checked)
options.ZipFlavor = 2;
else if (this.radioFlavorSfxGui.Checked)
options.ZipFlavor = 1;
else options.ZipFlavor = 0;
if (this.radioZip64AsNecessary.Checked)
options.Zip64 = Zip64Option.AsNecessary;
else if (this.radioZip64Always.Checked)
options.Zip64 = Zip64Option.Always;
else options.Zip64 = Zip64Option.Never;
options.Comment = String.Format("Encoding:{0} || Flavor:{1} || ZIP64:{2}\r\nCreated at {3} || {4}\r\n",
options.Encoding,
FlavorToString(options.ZipFlavor),
options.Zip64.ToString(),
System.DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss"),
this.Text);
if (this.tbComment.Text != TB_COMMENT_NOTE)
options.Comment += this.tbComment.Text;
_workerThread = new Thread(this.DoSave);
_workerThread.Name = "Zip Saver thread";
_workerThread.Start(options);
this.Cursor = Cursors.WaitCursor;
}
private void DoSave(Object p)
{
WorkerOptions options = p as WorkerOptions;
try
{
using (var zip1 = new ZipFile())
{
zip1.ProvisionalAlternateEncoding = System.Text.Encoding.GetEncoding(options.Encoding);
zip1.Comment = options.Comment;
zip1.AddDirectory(options.Folder);
_entriesToZip = zip1.EntryFileNames.Count;
SetProgressBars();
zip1.SaveProgress += this.zip1_SaveProgress;
zip1.UseZip64WhenSaving = options.Zip64;
if (options.ZipFlavor == 1)
zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.WinFormsApplication);
else if (options.ZipFlavor == 2)
zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.ConsoleApplication);
else
zip1.Save(options.ZipName);
}
}
catch (System.Exception exc1)
{
MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message));
btnCancel_Click(null, null);
}
}
void zip1_SaveProgress(object sender, SaveProgressEventArgs element)
{
switch (element.EventType)
{
case ZipProgressEventType.Saving_AfterWriteEntry:
StepArchiveProgress(element);
break;
case ZipProgressEventType.Saving_EntryBytesRead:
StepEntryProgress(element);
break;
case ZipProgressEventType.Saving_Completed:
SaveCompleted();
break;
case ZipProgressEventType.Saving_AfterSaveTempArchive:
// this event only occurs when saving an SFX file
TempArchiveSaved();
break;
}
if (_saveCanceled)
element.Cancel = true;
}
private void StepArchiveProgress(SaveProgressEventArgs element)
{
if (this.progressBar1.InvokeRequired)
{
this.progressBar1.Invoke(new SaveEntryProgress(this.StepArchiveProgress), new object[] { element });
}
else
{
if (!_saveCanceled)
{
_nFilesCompleted++;
this.progressBar1.PerformStep();
_totalBytesAfterCompress += element.CurrentEntry.CompressedSize;
_totalBytesBeforeCompress += element.CurrentEntry.UncompressedSize;
// reset the progress bar for the entry:
this.progressBar2.Value = this.progressBar2.Maximum = 1;
this.Update();
}
}
}
private void StepEntryProgress(SaveProgressEventArgs element)
{
if (this.progressBar2.InvokeRequired)
{
this.progressBar2.Invoke(new SaveEntryProgress(this.StepEntryProgress), new object[] { element });
}
else
{
if (!_saveCanceled)
{
if (this.progressBar2.Maximum == 1)
{
// reset
Int64 max = element.TotalBytesToTransfer;
_progress2MaxFactor = 0;
while (max > System.Int32.MaxValue)
{
max /= 2;
_progress2MaxFactor++;
}
this.progressBar2.Maximum = (int)max;
lblStatus.Text = String.Format("{0} of {1} files...({2})",
_nFilesCompleted + 1, _entriesToZip, element.CurrentEntry.FileName);
}
int xferred = element.BytesTransferred >> _progress2MaxFactor;
this.progressBar2.Value = (xferred >= this.progressBar2.Maximum)
? this.progressBar2.Maximum
: xferred;
this.Update();
}
}
}
private void SaveCompleted()
{
if (this.lblStatus.InvokeRequired)
{
this.lblStatus.Invoke(new MethodInvoker(this.SaveCompleted));
}
else
{
lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original.",
_nFilesCompleted, (100.00 * _totalBytesAfterCompress) / _totalBytesBeforeCompress);
ResetState();
}
}
private void ResetState()
{
this.btnCancel.Enabled = false;
this.btnOk.Enabled = true;
this.btnOk.Text = "Zip it!";
this.progressBar1.Value = 0;
this.progressBar2.Value = 0;
this.Cursor = Cursors.Default;
if (!_workerThread.IsAlive)
_workerThread.Join();
}
Remarks
Depending on the particular event, different properties on the SaveProgressEventArgs parameter are set. The following
table summarizes the available EventTypes and the conditions under
which this event handler is invoked with a
SaveProgressEventArgs with the given EventType.
| value of EntryType | Meaning and conditions |
|---|---|
| ZipProgressEventType.Saving_Started | Fired when ZipFile.Save() begins. |
| ZipProgressEventType.Saving_BeforeSaveEntry | Fired within ZipFile.Save(), just before writing data for each particular entry. |
| ZipProgressEventType.Saving_AfterSaveEntry | Fired within ZipFile.Save(), just after having finished writing data for each particular entry. |
| ZipProgressEventType.Saving_Completed | Fired when ZipFile.Save() has completed. |
| ZipProgressEventType.Saving_AfterSaveTempArchive | Fired after the temporary file has been created. This happens only when saving to a disk file. This event will not be invoked when saving to a stream. |
| ZipProgressEventType.Saving_BeforeRenameTempArchive | Fired just before renaming the temporary file to the permanent location. This happens only when saving to a disk file. This event will not be invoked when saving to a stream. |
| ZipProgressEventType.Saving_AfterRenameTempArchive | Fired just after renaming the temporary file to the permanent location. This happens only when saving to a disk file. This event will not be invoked when saving to a stream. |
| ZipProgressEventType.Saving_AfterCompileSelfExtractor | Fired after a self-extracting archive has finished compiling. This EventType is used only within SaveSelfExtractor(). |
| ZipProgressEventType.Saving_BytesRead | Set during the save of a particular entry, to update progress of the Save(). When this EventType is set, the BytesTransferred is the number of bytes that have been read from the source stream. The TotalBytesToTransfer is the number of bytes in the uncompressed file. |
- See Also
ZipError
An event that is raised when an error occurs during open or read of files while saving a zip archive.
public event EventHandler<ZipErrorEventArgs> ZipError
Event Type
Examples
This example shows how to use an event handler to handle errors during save of the zip file.
public static void MyZipError(object sender, ZipErrorEventArgs element)
{
Console.WriteLine("Error saving {0}...", element.FileName);
Console.WriteLine(" Exception: {0}", element.exception);
ZipEntry entry = element.CurrentEntry;
string response = null;
// Ask the user whether he wants to skip this error or not
do
{
Console.Write("Retry, Skip, Throw, or Cancel ? (R/S/T/C) ");
response = Console.ReadLine();
Console.WriteLine();
} while (response != null &&
response[0]!='S' && response[0]!='s' &&
response[0]!='R' && response[0]!='r' &&
response[0]!='T' && response[0]!='t' &&
response[0]!='C' && response[0]!='c');
element.Cancel = (response[0]=='C' || response[0]=='c');
if (response[0]=='S' || response[0]=='s')
entry.ZipErrorAction = ZipErrorAction.Skip;
else if (response[0]=='R' || response[0]=='r')
entry.ZipErrorAction = ZipErrorAction.Retry;
else if (response[0]=='T' || response[0]=='t')
entry.ZipErrorAction = ZipErrorAction.Throw;
}
public void SaveTheFile()
{
string directoryToZip = "fodder";
string directoryInArchive = "files";
string zipFileToCreate = "Archive.zip";
using (var zip = new ZipFile())
{
// set the event handler before adding any entries
zip.ZipError += MyZipError;
zip.AddDirectory(directoryToZip, directoryInArchive);
zip.Save(zipFileToCreate);
}
}
Private Sub MyZipError(ByVal sender As Object, ByVal element As Ionic.Zip.ZipErrorEventArgs)
' At this point, the application could prompt the user for an action to take.
' But in this case, this application will simply automatically skip the file, in case of error.
Console.WriteLine("Zip Error, entry {0}", element.CurrentEntry.FileName)
Console.WriteLine(" Exception: {0}", element.exception)
' set the desired ZipErrorAction on the CurrentEntry to communicate that to DotNetZip
element.CurrentEntry.ZipErrorAction = Zip.ZipErrorAction.Skip
End Sub
Public Sub SaveTheFile()
Dim directoryToZip As String = "fodder"
Dim directoryInArchive As String = "files"
Dim zipFileToCreate as String = "Archive.zip"
Using zipArchive As ZipFile = New ZipFile
' set the event handler before adding any entries
AddHandler zipArchive.ZipError, AddressOf MyZipError
zipArchive.AddDirectory(directoryToZip, directoryInArchive)
zipArchive.Save(zipFileToCreate)
End Using
End Sub
Remarks
Errors can occur as a file is being saved to the zip archive. For
example, the File.Open may fail, or a File.Read may fail, because of
lock conflicts or other reasons. If you add a handler to this event,
you can handle such errors in your own code. If you don't add a
handler, the library will throw an exception if it encounters an I/O
error during a call to Save().
Setting a handler implicitly sets ZipErrorAction to
ZipErrorAction.InvokeErrorEvent.
The handler you add applies to all ZipEntry items that are
subsequently added to the ZipFile instance. If you set this
property after you have added items to the ZipFile, but before you
have called Save(), errors that occur while saving those items
will not cause the error handler to be invoked.
If you want to handle any errors that occur with any entry in the zip file using the same error handler, then add your error handler once, before adding any entries to the zip archive.
In the error handler method, you need to set the ZipErrorAction property on the
ZipErrorEventArgs.CurrentEntry. This communicates back to
DotNetZip what you would like to do with this particular error. Within
an error handler, if you set the ZipEntry.ZipErrorAction property
on the ZipEntry to ZipErrorAction.InvokeErrorEvent or if
you don't set it at all, the library will throw the exception. (It is the
same as if you had set the ZipEntry.ZipErrorAction property on the
ZipEntry to ZipErrorAction.Throw.) If you set the
ZipErrorEventArgs.Cancel to true, the entire Save() will be
canceled.
In the case that you use ZipErrorAction.Skip, implying that
you want to skip the entry for which there's been an error, DotNetZip
tries to seek backwards in the output stream, and truncate all bytes
written on behalf of that particular entry. This works only if the
output stream is seekable. It will not work, for example, when using
ASPNET's Response.OutputStream.
- See Also