From 9d239d85bd70c5da0fce52f5a418fd1fa2562619 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 28 Jul 2014 09:18:38 +0200 Subject: [PATCH] Cut up Core into something we can use --- ext/Ionic.Zip.dll | Bin 0 -> 462336 bytes ext/Ionic.Zip.xml | 18151 ++++++++++++++++++++++++++++++++++ src/BinaryPatchUtility.cs | 2 +- src/ContentType.cs | 13 +- src/DeltaPackage.cs | 9 +- src/EnumerableExtensions.cs | 281 + src/PackageExtensions.cs | 17 + src/ReleaseEntry.cs | 31 +- src/ReleaseExtensions.cs | 49 + src/ReleasePackage.cs | 5 +- src/Utility.cs | 108 +- src/packages.config | 1 + 12 files changed, 18595 insertions(+), 72 deletions(-) create mode 100644 ext/Ionic.Zip.dll create mode 100644 ext/Ionic.Zip.xml create mode 100644 src/EnumerableExtensions.cs create mode 100644 src/PackageExtensions.cs create mode 100644 src/ReleaseExtensions.cs diff --git a/ext/Ionic.Zip.dll b/ext/Ionic.Zip.dll new file mode 100644 index 0000000000000000000000000000000000000000..26ce52a3fd539077e9bc3565cfd70984999900b7 GIT binary patch literal 462336 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 z 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

Cb+SL;^mQg?|90%gg?D+Evw5doD& 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 z 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 b`s=y-1X3WhNC9KQL!ZF9J+IRLoC5y>XuIjE literal 0 HcmV?d00001 diff --git a/ext/Ionic.Zip.xml b/ext/Ionic.Zip.xml new file mode 100644 index 00000000..faad034f --- /dev/null +++ b/ext/Ionic.Zip.xml @@ -0,0 +1,18151 @@ + + + + Ionic.Zip + + + +

+ Represents a Zlib stream for compression or decompression. + + + + + The ZlibStream is a Decorator on a . It adds ZLIB compression or decompression to any + stream. + + + Using this stream, applications can compress or decompress data via + stream Read() and Write() operations. Either compresssion or + decompression can occur through either reading or writing. The compression + format used is ZLIB, which is documented in IETF RFC 1950, "ZLIB Compressed + Data Format Specification version 3.3". This implementation of ZLIB always uses + DEFLATE as the compression method. (see IETF RFC 1951, "DEFLATE + Compressed Data Format Specification version 1.3.") + + + The ZLIB format allows for varying compression methods, window sizes, and dictionaries. + This implementation always uses the DEFLATE compression method, a preset dictionary, + and 15 window bits by default. + + + + This class is similar to , except that it adds the + RFC1950 header and trailer bytes to a compressed stream when compressing, or expects + the RFC1950 header and trailer bytes when decompressing. It is also similar to the + . + + + + + + + + Create a ZlibStream using the specified CompressionMode. + + + + + When mode is CompressionMode.Compress, the ZlibStream + will use the default compression level. The "captive" stream will be + closed when the ZlibStream is closed. + + + + + + This example uses a ZlibStream to compress a file, and writes the + compressed data to another file. + + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(fileToCompress + ".zlib")) + { + using (Stream compressor = new ZlibStream(raw, CompressionMode.Compress)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n; + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(fileToCompress & ".zlib") + Using compressor As Stream = New ZlibStream(raw, CompressionMode.Compress) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + + The stream which will be read or written. + Indicates whether the ZlibStream will compress or decompress. + + + + Create a ZlibStream using the specified CompressionMode and + the specified CompressionLevel. + + + + + + When mode is CompressionMode.Decompress, the level parameter is ignored. + The "captive" stream will be closed when the ZlibStream is closed. + + + + + + This example uses a ZlibStream to compress data from a file, and writes the + compressed data to another file. + + + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(fileToCompress + ".zlib")) + { + using (Stream compressor = new ZlibStream(raw, + CompressionMode.Compress, + CompressionLevel.BestCompression)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n; + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(fileToCompress & ".zlib") + Using compressor As Stream = New ZlibStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + + The stream to be read or written while deflating or inflating. + Indicates whether the ZlibStream will compress or decompress. + A tuning knob to trade speed for effectiveness. + + + + Create a ZlibStream using the specified CompressionMode, and + explicitly specify whether the captive stream should be left open after + Deflation or Inflation. + + + + + + When mode is CompressionMode.Compress, the ZlibStream will use + the default compression level. + + + + This constructor allows the application to request that the captive stream + remain open after the deflation or inflation occurs. By default, after + Close() is called on the stream, the captive stream is also + closed. In some cases this is not desired, for example if the stream is a + that will be re-read after + compression. Specify true for the parameter to leave the stream + open. + + + + See the other overloads of this constructor for example code. + + + + + The stream which will be read or written. This is called the + "captive" stream in other places in this documentation. + Indicates whether the ZlibStream will compress or decompress. + true if the application would like the stream to remain + open after inflation/deflation. + + + + Create a ZlibStream using the specified CompressionMode + and the specified CompressionLevel, and explicitly specify + whether the stream should be left open after Deflation or Inflation. + + + + + + This constructor allows the application to request that the captive + stream remain open after the deflation or inflation occurs. By + default, after Close() is called on the stream, the captive + stream is also closed. In some cases this is not desired, for example + if the stream is a that will be + re-read after compression. Specify true for the parameter to leave the stream open. + + + + When mode is CompressionMode.Decompress, the level parameter is + ignored. + + + + + + + This example shows how to use a ZlibStream to compress the data from a file, + and store the result into another file. The filestream remains open to allow + additional data to be written to it. + + + using (var output = System.IO.File.Create(fileToCompress + ".zlib")) + { + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (Stream compressor = new ZlibStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, true)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n; + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + // can write additional data to the output stream here + } + + + Using output As FileStream = File.Create(fileToCompress & ".zlib") + Using input As Stream = File.OpenRead(fileToCompress) + Using compressor As Stream = New ZlibStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, True) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + ' can write additional data to the output stream here. + End Using + + + + The stream which will be read or written. + + Indicates whether the ZlibStream will compress or decompress. + + + true if the application would like the stream to remain open after + inflation/deflation. + + + + A tuning knob to trade speed for effectiveness. This parameter is + effective only when mode is CompressionMode.Compress. + + + + + Dispose the stream. + + + + This may or may not result in a Close() call on the captive + stream. See the constructors that have a leaveOpen parameter + for more information. + + + This method may be invoked in two distinct scenarios. If disposing + == true, the method has been called directly or indirectly by a + user's code, for example via the public Dispose() method. In this + case, both managed and unmanaged resources can be referenced and + disposed. If disposing == false, the method has been called by the + runtime from inside the object finalizer and this method should not + reference other objects; in that case only unmanaged resources must + be referenced or disposed. + + + + indicates whether the Dispose method was invoked by user code. + + + + + Flush the stream. + + + + + Read data from the stream. + + + + + + If you wish to use the ZlibStream to compress data while reading, + you can create a ZlibStream with CompressionMode.Compress, + providing an uncompressed data stream. Then call Read() on that + ZlibStream, and the data read will be compressed. If you wish to + use the ZlibStream to decompress data while reading, you can create + a ZlibStream with CompressionMode.Decompress, providing a + readable compressed data stream. Then call Read() on that + ZlibStream, and the data will be decompressed as it is read. + + + + A ZlibStream can be used for Read() or Write(), but + not both. + + + + + + The buffer into which the read data should be placed. + + + the offset within that data array to put the first byte read. + + the number of bytes to read. + + the number of bytes read + + + + Calling this method always throws a . + + + The offset to seek to.... + IF THIS METHOD ACTUALLY DID ANYTHING. + + + The reference specifying how to apply the offset.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + + nothing. This method always throws. + + + + Calling this method always throws a . + + + The new value for the stream length.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + + + + Write data to the stream. + + + + + + If you wish to use the ZlibStream to compress data while writing, + you can create a ZlibStream with CompressionMode.Compress, + and a writable output stream. Then call Write() on that + ZlibStream, providing uncompressed data as input. The data sent to + the output stream will be the compressed form of the data written. If you + wish to use the ZlibStream to decompress data while writing, you + can create a ZlibStream with CompressionMode.Decompress, and a + writable output stream. Then call Write() on that stream, + providing previously compressed data. The data sent to the output stream + will be the decompressed form of the data written. + + + + A ZlibStream can be used for Read() or Write(), but not both. + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Compress a string into a byte array using ZLIB. + + + + Uncompress it with . + + + + + + + + A string to compress. The string will first be encoded + using UTF8, then compressed. + + + The string in compressed form + + + + Compress a byte array into a new byte array using ZLIB. + + + + Uncompress it with . + + + + + + + A buffer to compress. + + + The data in compressed form + + + + Uncompress a ZLIB-compressed byte array into a single string. + + + + + + + A buffer containing ZLIB-compressed data. + + + The uncompressed string + + + + Uncompress a ZLIB-compressed byte array into a byte array. + + + + + + + A buffer containing ZLIB-compressed data. + + + The data in uncompressed form + + + + This property sets the flush behavior on the stream. + Sorry, though, not sure exactly how to describe all the various settings. + + + + + The size of the working buffer for the compression codec. + + + + + The working buffer is used for all stream operations. The default size is + 1024 bytes. The minimum size is 128 bytes. You may get better performance + with a larger buffer. Then again, you might not. You would have to test + it. + + + + Set this before the first call to Read() or Write() on the + stream. If you try to set it afterwards, it will throw. + + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the total bytes + written out, if used in writing, or the total bytes read in, if used in + reading. The count may refer to compressed bytes or uncompressed bytes, + depending on how you've used the stream. + + + + + Returns the "random" number at a specific index. + + the index + the random number + + + + The ZipFile type represents a zip archive file. + + + + + 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 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. + + + + + ZipFile can be used to read and extract zip files, in addition to + creating zip files. ZipOutputStream cannot read zip files. If you want + to use a stream to read zip files, check out the class. + + + + ZipOutputStream does not support the creation of segmented or spanned + zip files. + + + + ZipOutputStream cannot produce a self-extracting archive. + + + + + Be aware that the ZipFile class implements the 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. + + + + + + + Extracts all of the items in the zip archive, to the specified path in the + filesystem. The path can be relative or fully-qualified. + + + + + 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 + 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 , 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. + + + + + 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 + + + + + + + + The path to which the contents of the zipfile will be extracted. + The path can be relative or fully-qualified. + + + + + + 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. + + + + + + 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 , 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 or one of the similar methods. + + + + Calling this method is equivalent to setting the property and then calling . + + + + This method will send verbose output messages to the + , if it is set on the ZipFile instance. + + + + + 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 + + + + + The path to which the contents of the zipfile will be extracted. + The path can be relative or fully-qualified. + + + + The action to take if extraction would overwrite an existing file. + + + + + + Reads a zip file archive and returns the instance. + + + + + The stream is read using the default System.Text.Encoding, which is the + IBM437 codepage. + + + + + 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. + + + + The name of the zip archive to open. This can be a fully-qualified or relative + pathname. + + + . + + The instance read from the zip archive. + + + + + Reads a zip file archive from the named filesystem file using the + specified options. + + + + + 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. + + + + + + + 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 + + + + + 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. + + + + The name of the zip archive to open. + This can be a fully-qualified or relative pathname. + + + + The set of options to use when reading the zip file. + + + The ZipFile instance read from the zip archive. + + + + + + + Reads a zip file archive using the specified text encoding, the specified + TextWriter for status messages, and the specified ReadProgress event handler, + and returns the instance. + + + + The name of the zip archive to open. + This can be a fully-qualified or relative pathname. + + + + An event handler for Read operations. + + + + The System.IO.TextWriter to use for writing verbose status messages + during operations on 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, such as a System.IO.StringWriter. + + + + The System.Text.Encoding to use when reading in the zip archive. Be + careful specifying the encoding. If the value you use here is not the same + as the Encoding used when the zip archive was created (possibly by a + different archiver) you will get unexpected results and possibly exceptions. + + + The instance read from the zip archive. + + + + + Reads a zip archive from a stream. + + + + + + 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 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. + + + + + + + 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 + + + + the stream containing the zip data. + + The ZipFile instance read from the stream + + + + + Reads a zip file archive from the given stream using the + specified options. + + + + + + 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 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. + + + + the stream containing the zip data. + + + The set of options to use when reading the zip file. + + + + Thrown if the zip archive cannot be read. + + + The ZipFile instance read from the stream. + + + + + + + Reads a zip archive from a stream, using the specified text Encoding, the + specified TextWriter for status messages, + and the specified ReadProgress event handler. + + + + + 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 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). Another example might be a stream being read from a database, where + the zip content is embedded within an aggregate stream of data. + + + + the stream containing the zip data. + + + The System.IO.TextWriter to which verbose status messages are written + during operations on the ZipFile. For example, in a console + application, System.Console.Out works, and will get a message for each entry + added to the ZipFile. If the TextWriter is null, no verbose messages + are written. + + + + The text encoding to use when reading entries that do not have the UTF-8 + encoding bit set. Be careful specifying the encoding. If the value you use + here is not the same as the Encoding used when the zip archive was created + (possibly by a different archiver) you will get unexpected results and + possibly exceptions. See the + property for more information. + + + + An event handler for Read operations. + + + an instance of ZipFile + + + + Checks the given file to see if it appears to be a valid zip file. + + + + + Calling this method is equivalent to calling with the testExtract parameter set to false. + + + + The file to check. + true if the file appears to be a zip file. + + + + Checks a file to see if it is a valid zip file. + + + + + 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 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 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. + + + + + The zip file to check. + true if the caller wants to extract each entry. + true if the file contains a valid zip file. + + + + Checks a stream to see if it contains a valid zip archive. + + + + + 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 . + + + + 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. + + + + + + The stream to check. + true if the caller wants to extract each entry. + true if the stream contains a valid zip archive. + + + + Generic IEnumerator support, for use of a ZipFile in an enumeration. + + + + You probably do not want to call GetEnumerator explicitly. Instead + it is implicitly called when you use a loop in C#, or a + For Each loop in VB.NET. + + + + 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 + + + + A generic enumerator suitable for use within a foreach loop. + + + + An IEnumerator, for use of a ZipFile in a foreach construct. + + + + 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). + + + + The IEnumerator over the entries in the ZipFile. + + + + + Adds to the ZipFile a set of files from the current working directory on + disk, that conform to the specified criteria. + + + + + 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,S,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. + + + + + 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 + + + + The criteria for file selection + + + + Adds to the ZipFile a set of files from the disk that conform to the + specified criteria, optionally recursing into subdirectories. + + + + + 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 . + + + + + + + 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 + + + + The criteria for file selection + + + If true, the file selection will recurse into subdirectories. + + + + + Adds to the ZipFile a set of files from a specified directory in the + filesystem, that conform to the specified criteria. + + + + + 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 . + + + + + + + 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 + + + + The criteria for file selection + + + The name of the directory on the disk from which to select files. + + + + + Adds to the ZipFile a set of files from the specified directory on disk, + that conform to the specified criteria. + + + + + + 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 . + + + + + + 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 + + + + The criteria for file selection + + + The filesystem path from which to select files. + + + + If true, the file selection will recurse into subdirectories. + + + + + 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. + + + + + 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 . + + + + + + + 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 + + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies 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 use directoryOnDisk, plus any subdirectory. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + 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. + + + + 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 . + + + + + 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 + + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies 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 use directoryOnDisk, plus any subdirectory. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + If true, the method also scans subdirectories for files matching the + criteria. + + + + + Updates the ZipFile with a selection of files from the disk that conform + to the specified criteria. + + + + 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 . + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies 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 use directoryOnDisk, plus any + subdirectory. Passing the empty string ("") will insert the item at + the root path within the archive. + + + + If true, the method also scans subdirectories for files matching the criteria. + + + + + + + Retrieve entries from the zipfile by specified criteria. + + + + + 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 . + + + + 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. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + 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 + + + the string that specifies which entries to select + a collection of ZipEntry objects that conform to the inclusion spec + + + + Retrieve entries from the zipfile by specified criteria. + + + + + 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 . + + + + 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. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + + 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 + + + the string that specifies which entries to select + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + a collection of ZipEntry objects that conform to the inclusion spec + + + + Remove entries from the zipfile by specified criteria. + + + + + 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 . + + + + 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. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + 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 + + + the string that specifies which entries to select + the number of entries removed + + + + Remove entries from the zipfile by specified criteria, and within the specified + path in the archive. + + + + + 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 . + + + + 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. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + + 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 + + + + the string that specifies which entries to select + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + the number of entries removed + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + 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 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 . + + + + + 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"); + } + + + the selection criteria for entries to extract. + + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + 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 + parameter. + + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + + 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); + } + + + + the selection criteria for entries to extract. + + + The action to take if extraction would overwrite an existing file. + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + 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 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 . + + + + + 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"); + } + + + + the selection criteria for entries to extract. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + 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 . + + + + the selection criteria for entries to extract. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + the directory on the disk into which to extract. It will be created + if it does not exist. + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + 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 + parameter. + + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + + 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); + } + + + + the selection criteria for entries to extract. + + + The directory on the disk into which to extract. It will be created if it does not exist. + + + + The directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + The action to take if extraction would overwrite an existing file. + + + + + + Saves the ZipFile instance to a self-extracting zip archive. + + + + + + The generated exe image will execute on any machine that has the .NET + Framework 2.0 installed on it. The generated exe image is also a + valid ZIP file, readable with DotNetZip or another Zip library or tool + such as WinZip. + + + + There are two "flavors" of self-extracting archive. The + WinFormsApplication version will pop up a GUI and allow the + user to select a target directory into which to extract. There's also + a checkbox allowing the user to specify to overwrite existing files, + and another checkbox to allow the user to request that Explorer be + opened to see the extracted files after extraction. The other flavor + is ConsoleApplication. A self-extractor generated with that + flavor setting will run from the command line. It accepts command-line + options to set the overwrite behavior, and to specify the target + extraction directory. + + + + There are a few temporary files created during the saving to a + self-extracting zip. These files are created in the directory pointed + to by , which defaults to . These temporary files are + removed upon successful completion of this method. + + + + When a user runs the WinForms SFX, the user's personal directory (Environment.SpecialFolder.Personal) + will be used as the default extract location. If you want to set the + default extract location, you should use the other overload of + SaveSelfExtractor()/ The user who runs the SFX will have the + opportunity to change the extract directory before extracting. When + the user runs the Command-Line SFX, the user must explicitly specify + the directory to which to extract. The .NET Framework 2.0 is required + on the computer when the self-extracting archive is run. + + + + NB: This method is not available in the version of DotNetZip build for + the .NET Compact Framework, nor in the "Reduced" DotNetZip library. + + + + + + + string DirectoryPath = "c:\\Documents\\Project7"; + using (ZipFile zip = new ZipFile()) + { + zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); + zip.Comment = "This will be embedded into a self-extracting console-based exe"; + zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication); + } + + + Dim DirectoryPath As String = "c:\Documents\Project7" + Using zip As New ZipFile() + zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) + zip.Comment = "This will be embedded into a self-extracting console-based exe" + zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication) + End Using + + + + + a pathname, possibly fully qualified, to be created. Typically it + will end in an .exe extension. + + Indicates whether a Winforms or Console self-extractor is + desired. + + + + Saves the ZipFile instance to a self-extracting zip archive, using + the specified save options. + + + + + This method saves a self extracting archive, using the specified save + options. These options include the flavor of the SFX, the default extract + directory, the icon file, and so on. See the documentation + for for more + details. + + + + The user who runs the SFX will have the opportunity to change the extract + directory before extracting. If at the time of extraction, the specified + directory does not exist, the SFX will create the directory before + extracting the files. + + + + + + This example saves a WinForms-based self-extracting archive EXE that + will use c:\ExtractHere as the default extract location. The C# code + shows syntax for .NET 3.0, which uses an object initializer for + the SelfExtractorOptions object. + + string DirectoryPath = "c:\\Documents\\Project7"; + using (ZipFile zip = new ZipFile()) + { + zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); + zip.Comment = "This will be embedded into a self-extracting WinForms-based exe"; + var options = new SelfExtractorOptions + { + Flavor = SelfExtractorFlavor.WinFormsApplication, + DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere", + PostExtractCommandLine = ExeToRunAfterExtract, + SfxExeWindowTitle = "My Custom Window Title", + RemoveUnpackedFilesAfterExecute = true + }; + zip.SaveSelfExtractor("archive.exe", options); + } + + + Dim DirectoryPath As String = "c:\Documents\Project7" + Using zip As New ZipFile() + zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) + zip.Comment = "This will be embedded into a self-extracting console-based exe" + Dim options As New SelfExtractorOptions() + options.Flavor = SelfExtractorFlavor.WinFormsApplication + options.DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere" + options.PostExtractCommandLine = ExeToRunAfterExtract + options.SfxExeWindowTitle = "My Custom Window Title" + options.RemoveUnpackedFilesAfterExecute = True + zip.SaveSelfExtractor("archive.exe", options) + End Using + + + + The name of the EXE to generate. + provides the options for creating the + Self-extracting archive. + + + + Delete file with retry on UnauthorizedAccessException. + + + + + When calling File.Delete() on a file that has been "recently" + created, the call sometimes fails with + UnauthorizedAccessException. This method simply retries the Delete 3 + times with a sleep between tries. + + + + the name of the file to be deleted + + + + Saves the Zip archive to a file, specified by the Name property of the + ZipFile. + + + + + The ZipFile instance is written to storage, typically a zip file + in a filesystem, only when the caller calls Save. In the typical + case, the Save operation writes the zip content to a temporary file, and + then renames the temporary file to the desired name. If necessary, this + method will delete a pre-existing file before the rename. + + + + The 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 a 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 a dynamically-allocated + MemoryStream, the memory stream must not have been disposed + before the call to Save. See the 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. + + + + + + + + Thrown if you haven't specified a location or stream for saving the zip, + either in the constructor or by setting the Name property, or if you try + to save a regular zip archive to a filename with a .exe extension. + + + + Thrown if 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. + + + + + + Save the file to a new zipfile, with the given name. + + + + + This method allows the application to explicitly specify the name of the zip + file when saving. Use this when creating a new zip file, or when + updating a zip archive. + + + + An application can also save a zip archive in several places by calling this + method multiple times in succession, with different filenames. + + + + The ZipFile instance is written to storage, typically a zip file in a + filesystem, only when the caller calls Save. The Save operation writes + the zip content to a temporary file, and then renames the temporary file + to the desired name. If necessary, this method will delete a pre-existing file + before the rename. + + + + + + Thrown if you specify a directory for the filename. + + + + The name of the zip archive to save to. Existing files will + be overwritten with great prejudice. + + + + This example shows how to create and Save a 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 a 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 + + + + + + + Save the zip archive to the specified stream. + + + + + The ZipFile instance is written to storage - typically a zip file + in a filesystem, but using this overload, the storage can be anything + accessible via a writable stream - only when the caller calls Save. + + + + Use this method to save the zip content to a stream directly. A common + scenario is an ASP.NET application that dynamically generates a zip file + and allows the browser to download it. The application can call + Save(Response.OutputStream) to write a zipfile directly to the + output stream, without creating a zip file on the disk on the ASP.NET + server. + + + + Be careful when saving a file to a non-seekable stream, including + Response.OutputStream. When DotNetZip writes to a non-seekable + stream, the zip archive is formatted in such a way that may not be + compatible with all zip tools on all platforms. It's a perfectly legal + and compliant zip file, but some people have reported problems opening + files produced this way using the Mac OS archive utility. + + + + + + + This example saves the zipfile content into a MemoryStream, and + then gets the array of bytes from that MemoryStream. + + + using (var zip = new Ionic.Zip.ZipFile()) + { + zip.CompressionLevel= Ionic.Zlib.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 a pitfall you should avoid. DO NOT read + from a stream, then try to save to the same stream. DO + NOT DO THIS: + + + + using (var fs = new FileSteeam(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! + } + + + + + + The System.IO.Stream to write to. It must be + writable. If you created the ZipFile instanct by calling + ZipFile.Read(), this stream must not be the same stream + you passed to ZipFile.Read(). + + + + + Adds an item, either a file or a directory, to a zip file archive. + + + + + 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 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 + . + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + This method has two overloads. + + the name of the file or directory to add. + + The ZipEntry added. + + + + 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. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + Thrown if the file or directory passed in does not exist. + + + the name of the file or directory to add. + + + + The 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 (Nothing in VB) will use the + path on the fileOrDirectoryName. Passing the empty string ("") will + insert the item at the root path within the archive. + + + + + + + + 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 + + + The ZipEntry added. + + + + Adds a File to a Zip file archive. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + 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 + + + + This method has two overloads. + + + + + + + The 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. + + The ZipEntry corresponding to the File added. + + + + Adds a File to a Zip file archive, potentially overriding the path to be + used within the zip archive. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + 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 + + + + + + + + + The name of the file to add. The name of the file may be a relative path + or a fully-qualified path. + + + + Specifies 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 (Nothing in + 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. + + + The ZipEntry corresponding to the file added. + + + + This method removes a collection of entries from the ZipFile. + + + + 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. + + + + + + + + This method removes a collection of entries from the ZipFile, by name. + + + + 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. + + + + + + + + This method adds a set of files to the ZipFile. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + 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. + + + + 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 + + + + + + + + Adds or updates a set of files in the ZipFile. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + 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. + + + + + + Adds a set of files to the ZipFile, using the + specified directory path in the archive. + + + + + 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 , , , , , , and , their respective values at the + time of this call will be applied to each ZipEntry added. + + + + + 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. + + + + Specifies 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 (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + + + 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. + + + + + + Think of the as a "root" or + base directory used in the archive for the files that get added. when + 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 , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + 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. + + + + Specifies 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 (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + whether the entries in the zip archive will reflect the directory + hierarchy that is present in the various filenames. For example, if + includes two paths, + \Animalia\Chordata\Mammalia\Info.txt and + \Plantae\Magnoliophyta\Dicotyledon\Info.txt, then calling this method + with = false will + result in an exception because of a duplicate entry name, while + calling this method with = + true will result in the full direcory paths being included in + the entries added to the ZipFile. + + + + + + Adds or updates a set of files to the ZipFile, using the specified + directory path in the archive. + + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + 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. + + + + Specifies 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 (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + + + Adds or Updates a File in a Zip file archive. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + 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 + + + + + + + + + The 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. + + + + The ZipEntry corresponding to the File that was added or updated. + + + + + Adds or Updates a File in a Zip file archive. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The 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. + + + + Specifies 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 (Nothing in 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. + + + + The ZipEntry corresponding to the File that was added or updated. + + + + + Add or update a directory in a zip archive. + + + + 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. + + + + + + + + The path to the directory to be added to the zip archive, or updated in + the zip archive. + + + + The ZipEntry corresponding to the Directory that was added or updated. + + + + + Add or update a directory in the zip archive at the specified root + directory in the archive. + + + + 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. + + + + + + + + The path to the directory to be added to the zip archive, or updated + in the zip archive. + + + + Specifies 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. Passing + null (Nothing in VB) will use the path on the + directoryName, if any. Passing the empty string ("") will insert + the item at the root path within the archive. + + + + The ZipEntry corresponding to the Directory that was added or updated. + + + + + Add or update a file or directory in the zip archive. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + the path to the file or directory to be added or updated. + + + + + Add or update a file or directory. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The path for the File or Directory to be added or updated. + + + Specifies 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. Passing + null (Nothing in VB) will use the path on the + itemName, if any. Passing the empty string ("") will insert the + item at the root path within the archive. + + + + + Adds a named entry into the zip archive, taking content for the entry + from a string. + + + + 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, or on Silverlight, using UTF-8. + + + + The content of the file, should it be extracted from the zip. + + + + The name, including any path, to use for the entry within the archive. + + + The ZipEntry added. + + + + 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 + + + + + + Adds a named entry into the zip archive, taking content for the entry + from a string, and using the specified text encoding. + + + + + + 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 . + + + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + + The 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 . + + + The ZipEntry added. + + + + + Create an entry in the ZipFile using the given Stream + as input. The entry will have the given filename. + + + + + + The application should provide an open, readable stream; in this case it + will be read during the call to 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 + overload. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + 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 + + + + + + + The name, including any path, which is shown in the zip file for the added + entry. + + + The input stream from which to grab content for the file + + The ZipEntry added. + + + + Add a ZipEntry for which content is written directly by the application. + + + + + 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 , , , , , + , and , 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. + + + + + the name of the entry to add + the delegate which will write the entry content + the ZipEntry added + + + + 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 + + + + + + Add an entry, for which the application will provide a stream + containing the entry data, on a just-in-time basis. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + 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 + + + + + the name of the entry to add + + the 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. + + + the 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. + + the ZipEntry added + + + + + Updates the given entry in the ZipFile, using the given + string as content for the ZipEntry. + + + + + + Calling this method is equivalent to removing the ZipEntry for + the given file name and directory path, if it exists, and then calling + . See the documentation for + that method for further explanation. The string content is encoded + using the default encoding for the machine, or on Silverlight, using + UTF-8. This encoding is distinct from the encoding used for the + filename itself. See . + + + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given string as + content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + + The text encoding to use when encoding the string. Be aware: This is + distinct from the text encoding used to encode the filename. See . + + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given delegate + as the source for content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + the delegate which will write the entry content. + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given delegates + to open and close the stream that provides the content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + + the delegate that will be invoked to open the stream + + + the delegate that will be invoked to close the stream + + + The ZipEntry added or updated. + + + + + Updates the given entry in the ZipFile, using the given stream as + input, and the given filename and given directory Path. + + + + + 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 property. Check the + documentation of that property for more information. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The name, including any path, to use within the archive for the entry. + + + The input stream from which to read file data. + The ZipEntry added. + + + + 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. + + + The data to use for the entry. + + + The name, including any path, to use within the archive for the entry. + + + The ZipEntry added. + + + + Updates the given entry in the ZipFile, using the given byte + array as content for the entry. + + + + Calling this method is equivalent to removing the ZipEntry + for the given filename and directory path, if it exists, and then + calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + The content to use for the ZipEntry. + + The ZipEntry added. + + + + + Adds the contents of a filesystem directory to a Zip file archive. + + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + + + + + This method has 2 overloads. + + The name of the directory to add. + The ZipEntry added. + + + + Adds the contents of a filesystem directory to a Zip file archive, + overriding the path to be used for entries in the archive. + + + + + 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 , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + + 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); + } + } + + + + + + + + The name of the directory to add. + + + Specifies 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 + (Nothing in VB) or the empty string ("") will insert the items at + the root path within the archive. + + + The ZipEntry added. + + + + Creates a directory in the zip archive. + + + + + + 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. + + + + + + The name of the directory to create in the archive. + + The ZipEntry added. + + + + Returns true if an entry by the given name exists in the ZipFile. + + + the name of the entry to find + true if an entry with the given name exists; otherwise false. + + + + Provides a string representation of the instance. + a string representation of the instance. + + + + Creates a new ZipFile instance, using the specified filename. + + + + + 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 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? + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + + 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 + + + + The filename to use for the new zip archive. + + + + + Creates a new ZipFile instance, using the specified name for the + filename, and the specified Encoding. + + + + + 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 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. + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + The filename to use for the new zip archive. + The Encoding is used as the default alternate + encoding for entries with filenames or comments that cannot be encoded + with the IBM437 code page. + + + + Create a zip file, without specifying a target filename or stream to save to. + + + + + 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 or + to save to a file or a + stream, respectively. The application can also set the + property and then call the no-argument method. (This + is the preferred approach for applications that use the library through + COM interop.) If you call the no-argument 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. + + + + + 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 + + + + + + Create a zip file, specifying a text Encoding, but without specifying a + target filename or stream to save to. + + + + + 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. + + + + + Creates a new ZipFile instance, using the specified name for the + filename, and the specified status message writer. + + + + + 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. + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + + + 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 + + + + The filename to use for the new zip archive. + A TextWriter to use for writing + verbose status messages. + + + + Creates a new ZipFile instance, using the specified name for the + filename, the specified status message writer, and the specified Encoding. + + + + + 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 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. + + + + + + Thrown if fileName refers to an existing file that is not a valid zip file. + + + The filename to use for the new zip archive. + A TextWriter to use for writing verbose + status messages. + + The Encoding is used as the default alternate encoding for entries with + filenames or comments that cannot be encoded with the IBM437 code page. + + + + + Initialize a ZipFile instance by reading in a zip file. + + + + + + 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. + + + + the name of the existing zip file to read in. + + + + Removes the given ZipEntry from the zip archive. + + + + + After calling RemoveEntry, the application must call Save to + make the changes permanent. + + + + + Thrown if the specified ZipEntry does not exist in the ZipFile. + + + + 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 + + + + + The ZipEntry to remove from the zip. + + + + + + + + Removes the ZipEntry with the given filename from the zip archive. + + + + + After calling RemoveEntry, the application must call Save to + make the changes permanent. + + + + + + Thrown if the ZipFile is not updatable. + + + + Thrown if a ZipEntry with the specified filename does not exist in + the ZipFile. + + + + + 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 + + + + + The 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 + CaseSensitiveRetrieval property to change this behavior. The + pathname can use forward-slashes or backward slashes. + + + + + + Closes the read and write streams associated + to the ZipFile, if necessary. + + + + 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. + + + + 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 + + + + + + Disposes any managed resources, if the flag is set, then marks the + instance disposed. This method is typically not called explicitly from + application code. + + + + Applications should call the no-arg Dispose method. + + + + indicates whether the method should dispose streams or not. + + + + + Default size of the buffer used for IO. + + + + + Checks a zip file to see if its directory is consistent. + + + + + + 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 or Compact Framework + versions of DotNetZip. + + + + Developers using COM can use the ComHelper.CheckZip(String) + method. + + + + + The filename to of the zip file to check. + + true if the named zip file checks OK. Otherwise, false. + + + + + + + Checks a zip file to see if its directory is consistent, + and optionally fixes the directory if necessary. + + + + + + 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 or Compact + Framework versions of DotNetZip. + + + + + The filename to of the zip file to check. + + If true, the method will fix the zip file if + necessary. + + + a TextWriter in which messages generated while checking will be written. + + + true if the named zip is OK; false if the file needs to be fixed. + + + + + + + Rewrite the directory within a zipfile. + + + + + + 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. + + + + + The filename to of the zip file to fix. + + + + + + + Verify the password on a zip file. + + + + + 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 + + + + The filename to of the zip file to fix. + + The password to check. + + a bool indicating whether the password matches. + + + + 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. + + + + + Depending on the particular event, different properties on the 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. + + + + + + + + + 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, e) => { + if (e.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 e) + { + if (e.EventType == ZipProgressEventType.Saving_Started) + Console.WriteLine("Saving: {0}", e.ArchiveName); + + else if (e.EventType == ZipProgressEventType.Saving_Completed) + { + justHadByteUpdate= false; + Console.WriteLine(); + Console.WriteLine("Done: {0}", e.ArchiveName); + } + + else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) + { + if (justHadByteUpdate) + Console.WriteLine(); + Console.WriteLine(" Writing: {0} ({1}/{2})", + e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal); + justHadByteUpdate= false; + } + + else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead) + { + if (justHadByteUpdate) + Console.SetCursorPosition(0, Console.CursorTop); + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, + e.BytesTransferred / (0.01 * e.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 e As SaveProgressEventArgs) + If (e.EventType Is ZipProgressEventType.Saving_Started) Then + Console.WriteLine("Saving: {0}", e.ArchiveName) + + ElseIf (e.EventType Is ZipProgressEventType.Saving_Completed) Then + justHadByteUpdate = False + Console.WriteLine + Console.WriteLine("Done: {0}", e.ArchiveName) + + ElseIf (e.EventType Is ZipProgressEventType.Saving_BeforeWriteEntry) Then + If justHadByteUpdate Then + Console.WriteLine + End If + Console.WriteLine(" Writing: {0} ({1}/{2})", e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal) + justHadByteUpdate = False + + ElseIf (e.EventType Is ZipProgressEventType.Saving_EntryBytesRead) Then + If justHadByteUpdate Then + Console.SetCursorPosition(0, Console.CursorTop) + End If + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, _ + e.TotalBytesToTransfer, _ + (CDbl(e.BytesTransferred) / (0.01 * e.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 e); + delegate void ButtonClick(object sender, EventArgs e); + + 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 e) + { + KickoffZipup(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + if (this.lblStatus.InvokeRequired) + { + this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, e }); + } + 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 e) + { + switch (e.EventType) + { + case ZipProgressEventType.Saving_AfterWriteEntry: + StepArchiveProgress(e); + break; + case ZipProgressEventType.Saving_EntryBytesRead: + StepEntryProgress(e); + break; + case ZipProgressEventType.Saving_Completed: + SaveCompleted(); + break; + case ZipProgressEventType.Saving_AfterSaveTempArchive: + // this event only occurs when saving an SFX file + TempArchiveSaved(); + break; + } + if (_saveCanceled) + e.Cancel = true; + } + + + + private void StepArchiveProgress(SaveProgressEventArgs e) + { + if (this.progressBar1.InvokeRequired) + { + this.progressBar1.Invoke(new SaveEntryProgress(this.StepArchiveProgress), new object[] { e }); + } + else + { + if (!_saveCanceled) + { + _nFilesCompleted++; + this.progressBar1.PerformStep(); + _totalBytesAfterCompress += e.CurrentEntry.CompressedSize; + _totalBytesBeforeCompress += e.CurrentEntry.UncompressedSize; + + // reset the progress bar for the entry: + this.progressBar2.Value = this.progressBar2.Maximum = 1; + + this.Update(); + } + } + } + + + private void StepEntryProgress(SaveProgressEventArgs e) + { + if (this.progressBar2.InvokeRequired) + { + this.progressBar2.Invoke(new SaveEntryProgress(this.StepEntryProgress), new object[] { e }); + } + else + { + if (!_saveCanceled) + { + if (this.progressBar2.Maximum == 1) + { + // reset + Int64 max = e.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, e.CurrentEntry.FileName); + } + + int xferred = e.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(); + } + + + + + + + + + + + An event handler invoked before, during, and after the reading of a zip archive. + + + + + Depending on the particular event being signaled, different properties on the + 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. + + + + + + + + + + + + + An event handler invoked before, during, and after extraction of + entries in the zip archive. + + + + + Depending on the particular event, different properties on the 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. + + + + + + + + + + private static bool justHadByteUpdate = false; + public static void ExtractProgress(object sender, ExtractProgressEventArgs e) + { + if(e.EventType == ZipProgressEventType.Extracting_EntryBytesWritten) + { + if (justHadByteUpdate) + Console.SetCursorPosition(0, Console.CursorTop); + + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, + e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); + justHadByteUpdate = true; + } + else if(e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) + { + if (justHadByteUpdate) + Console.WriteLine(); + Console.WriteLine("Extracting: {0}", e.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 e in zip1) + { + e.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 e As ZipEntry + For Each e In zip1 + e.Extract(TargetDir, True) + Next + End Using + End Sub + + Private Shared justHadByteUpdate As Boolean = False + + Public Shared Sub MyExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs) + If (e.EventType = ZipProgressEventType.Extracting_EntryBytesWritten) Then + If ExtractTest.justHadByteUpdate Then + Console.SetCursorPosition(0, Console.CursorTop) + End If + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) + ExtractTest.justHadByteUpdate = True + ElseIf (e.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry) Then + If ExtractTest.justHadByteUpdate Then + Console.WriteLine + End If + Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName) + ExtractTest.justHadByteUpdate = False + End If + End Sub + + + + + + + + + + An event handler invoked before, during, and after Adding entries to a zip archive. + + + + Adding a large number of entries to a zip file can take a long + time. For example, when calling 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. + + + + + + int _numEntriesToAdd= 0; + int _numEntriesAdded= 0; + void AddProgressHandler(object sender, AddProgressEventArgs e) + { + switch (e.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, e.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 e As AddProgressEventArgs) + Select Case e.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}", e.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 + + + + + + + + + + + + An event that is raised when an error occurs during open or read of files + while saving a zip archive. + + + + + 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 to + ZipErrorAction.InvokeErrorEvent. + + + + The handler you add applies to all 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 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. + + + + + + + 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 e) + { + Console.WriteLine("Error saving {0}...", e.FileName); + Console.WriteLine(" Exception: {0}", e.exception); + ZipEntry entry = e.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'); + + e.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 e 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}", e.CurrentEntry.FileName) + Console.WriteLine(" Exception: {0}", e.exception) + ' set the desired ZipErrorAction on the CurrentEntry to communicate that to DotNetZip + e.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 + + + + + + + + + Indicates whether to perform a full scan of the zip file when reading it. + + + + + + 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 . 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. + + + + + + + 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 + + + + + + + Whether to sort the ZipEntries before saving the file. + + + + The default is false. If you have a large number of zip entries, the sort + alone can consume significant time. + + + + + 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 + + + + + + + Indicates whether NTFS Reparse Points, like junctions, should be + traversed during calls to AddDirectory(). + + + + 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. + + + + + using (var zip = new ZipFile()) + { + zip.AddDirectoryWillTraverseReparsePoints = false; + zip.AddDirectory(dirToZip,"fodder"); + zip.Save(zipFileToCreate); + } + + + + + + Size of the IO buffer used while saving. + + + + + + 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. + + + + + + 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); + } + + + + + + Size of the work buffer to use for the ZLIB codec during compression. + + + + + 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. + + + + + + Indicates whether extracted files should keep their paths as + stored in the zip archive. + + + + + 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. + + + + + + + The compression strategy to use for all entries. + + + + 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 Ionic.Zlib.CompressionStrategy. + + + + + The name of the ZipFile, on disk. + + + + + + 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 , this name will + specify the name of the zip file created. Doing so is equivalent to + calling . 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. + + + + + + Sets the compression level to be used for entries subsequently added to + the zip archive. + + + + + 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 , , and , setting this property on a ZipFile + instance will cause the specified CompressionLevel to be used on all + 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. + + + + + + The compression method for the zipfile. + + + + By default, the compression method is CompressionMethod.Deflate. + + + + + + + A comment attached to the zip archive. + + + + + + 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 is + Never, it uses the default encoding (IBM437). (b) if is Always, it always uses the + alternate encoding (). (c) if 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 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 + alone, or specify it only + once, before adding any entries to the ZipFile instance. + + + + + + + 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. + + + + + 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 (), Access (), and Modified () 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 . + + + + 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 , , and . + + + + The value set here applies to all entries subsequently added to the + ZipFile. + + + + This property is not mutually exclusive of the 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. + + + + + 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 + + + + + + + + + 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. + + + + + 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 (), Access (), and Modified () 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 . + + + + 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 , , and . + + + + This property is not mutually exclusive of the 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. + + + + + + + + + Indicates whether verbose output is sent to the during AddXxx() and + ReadXxx() operations. + + + + This is a synthetic property. It returns true if the is non-null. + + + + + Indicates whether to perform case-sensitive matching on the filename when + retrieving entries in the zipfile via the string-based indexer. + + + + 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. + + + + + Indicates whether to encode entry filenames and entry comments using Unicode + (UTF-8). + + + + + 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 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. + + + + + + + Specify whether to use ZIP64 extensions when saving a zip archive. + + + + + + When creating a zip file, the default value for the property is . 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 property, after calling Save(). + + + + Have you thought about + donating? + + + + + + + + Indicates whether the archive requires ZIP64 extensions. + + + + + + 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 + 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 property is set to , or if the property is set to and the output stream was not + seekable. Use the property to determine if + the most recent Save() method resulted in an archive that utilized + the ZIP64 extensions. + + + + + + + + + Indicates whether the most recent Save() operation used ZIP64 extensions. + + + + + 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 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 , or because the + UseZip64WhenSaving property was set to and the output stream was not seekable. + The value of this property does not indicate the reason the ZIP64 + extensions were used. + + + + + + + + + Indicates whether the most recent Read() operation read a zip file that uses + ZIP64 extensions. + + + + This property will return null (Nothing in VB) if you've added an entry after reading + the zip file. + + + + + 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. + + + + + 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 and 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 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 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 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 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 property and calling Save(). + + + + + 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 + + + + DefaultEncoding + + + + A Text Encoding to use when encoding the filenames and comments for + all the ZipEntry items, during a ZipFile.Save() operation. + + + + Whether the encoding specified here is used during the save depends + on . + + + + + + 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. + + + + + The default text encoding used in zip archives. It is numeric 437, also + known as IBM437. + + + + + + Gets or sets the TextWriter to which status messages are delivered + for the instance. + + + + 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. + + + + + 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 + + + + + + + Gets or sets the name for the folder to store the temporary file + this library writes when saving a zip archive. + + + + + 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 property or via + the 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. + + + + + Thrown when setting the property if the directory does not exist. + + + + + + Sets the password to be used on the ZipFile instance. + + + + + + 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 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 , 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 . 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 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. + + + + + + + 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 + + + + + + ZipFile.Encryption + ZipEntry.Password + + + + The action the library should take when extracting a file that already + exists. + + + + + 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. + + + + + + + The action the library should take when an error is encountered while + opening or reading files as they are saved into a zip archive. + + + + + 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 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 , , and , setting this property on a ZipFile + instance will cause the specified ZipErrorAction to be used on all + 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 on the ZipFile before + calling Save(). A message will be emitted into that writer for + each skipped file, if any. + + + + + + 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 + + + + + + + + + + The Encryption to use for entries added to the ZipFile. + + + + + 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 . + + + + As with some other properties on the ZipFile class, like and , setting this + property on a ZipFile instance will cause the specified + EncryptionAlgorithm to be used on all 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 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. + + + + + + + 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 + + + + + ZipFile.Password + ZipEntry.Encryption + + + + A callback that allows the application to specify the compression level + to use for entries subsequently added to the zip archive. + + + + + + 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 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 + Ionic.Zlib.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. + + + + + + + The maximum size of an output segment, when saving a split Zip file. + + + + Set this to a non-zero value before calling or 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 and + then subsequently call ZipFile.Save(), unless you set this + property before calling Save(), you will get a normal, + single-file archive. + + + + + + + + Returns the number of segments used in the most recent Save() operation. + + + + This is normally zero, unless you have set the property. If you have set , 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. + + + + + + + The size threshold for an entry, above which a parallel deflate is used. + + + + + + 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 . You may have to + perform some tests to determine the best approach for your situation. + + + + + + + + + + The maximum number of buffer pairs to use when performing + parallel compression. + + + + + 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 (). 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(). + + + + + + + + + Returns the version number on the DotNetZip assembly. + + + + + 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. + + + + + + This is an integer indexer into the Zip archive. + + + + + 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. + + + + + + The ZipEntry within the Zip archive at the specified index. If the + entry does not exist in the archive, this indexer throws. + + + + + + This is a name-based indexer into the Zip archive. + + + + + This property is read-only. + + + + The 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. + + + + + + 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 + + + + + + Thrown if the caller attempts to assign a non-null value to the indexer. + + + + The 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 + property to change this behavior. The + pathname can use forward-slashes or backward slashes. + + + + The ZipEntry within the Zip archive, given by the specified + filename. If the named entry does not exist in the archive, this indexer + returns null (Nothing in VB). + + + + + + The list of filenames for the entries contained within the zip archive. + + + + 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. + + + + + + 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 + + + + + The list of strings for the filenames contained within the Zip archive. + + + + + + Returns the readonly collection of entries in the Zip archive. + + + + + + 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. + + + + + + + Returns a readonly collection of entries in the Zip archive, sorted by FileName. + + + + 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. + + + + + 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); + } + } + + + + + + + + Returns the number of entries in the Zip archive. + + + + + Provides a human-readable string with information about the ZipFile. + + + + + 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. + + + + + + Represents a single entry in a ZipFile. Typically, applications get a ZipEntry + by enumerating the entries within a ZipFile, or by adding an entry to a ZipFile. + + + + + generate and return a byte array that encodes the filename + for the entry. + + + + side effects: generate and store into _CommentBytes the + byte array for any comment attached to the entry. Also + sets _actualEncoding to indicate the actual encoding + used. The same encoding is used for both filename and + comment. + + + + + + Stores the position of the entry source stream, or, if the position is + already stored, seeks to that position. + + + + + This method is called in prep for reading the source stream. If PKZIP + encryption is used, then we need to calc the CRC32 before doing the + encryption, because the CRC is used in the 12th byte of the PKZIP + encryption header. So, we need to be able to seek backward in the source + when saving the ZipEntry. This method is called from the place that + calculates the CRC, and also from the method that does the encryption of + the file data. + + + + The first time through, this method sets the _sourceStreamOriginalPosition + field. Subsequent calls to this method seek to that position. + + + + + + Copy metadata that may have been changed by the app. We do this when + resetting the zipFile instance. If the app calls Save() on a ZipFile, then + tries to party on that file some more, we may need to Reset() it , which + means re-reading the entries and then copying the metadata. I think. + + + + + Set the input stream and get its length, if possible. The length is + used for progress updates, AND, to allow an optimization in case of + a stream/file of zero length. In that case we skip the Encrypt and + compression Stream. (like DeflateStream or BZip2OutputStream) + + + + + Prepare the given stream for output - wrap it in a CountingStream, and + then in a CRC stream, and an encryptor and deflator as appropriate. + + + + Previously this was used in ZipEntry.Write(), but in an effort to + introduce some efficiencies in that method I've refactored to put the + code inline. This method still gets called by ZipOutputStream. + + + + + + Reads one entry from the zip directory structure in the zip file. + + + + The zipfile for which a directory entry will be read. From this param, the + method gets the ReadStream and the expected text encoding + (ProvisionalAlternateEncoding) which is used if the entry is not marked + UTF-8. + + + + a list of previously seen entry names; used to prevent duplicates. + + + the entry read from the archive. + + + + Returns true if the passed-in value is a valid signature for a ZipDirEntry. + + the candidate 4-byte signature value. + true, if the signature is valid according to the PKWare spec. + + + + Reads one ZipEntry from the given stream. The content for + the entry does not get decompressed or decrypted. This method + basically reads metadata, and seeks. + + the ZipContainer this entry belongs to. + + true of this is the first entry being read from the stream. + + the ZipEntry read from the stream. + + + + Finds a particular segment in the given extra field. + This is used when modifying a previously-generated + extra field, in particular when removing the AES crypto + segment in the extra field. + + + + + At current cursor position in the stream, read the extra + field, and set the properties on the ZipEntry instance + appropriately. This can be called when processing the + Extra field in the Central Directory, or in the local + header. + + + + + Extract the entry to the filesystem, starting at the current + working directory. + + + + This method has a bunch of overloads! One of them is sure to + be the right one for you... If you don't like these, check + out the ExtractWithPassword() methods. + + + + + + + + + This method extracts an entry from a zip file into the current + working directory. The path of the entry as extracted is the full + path as specified in the zip archive, relative to the current + working directory. After the file is extracted successfully, the + file attributes and timestamps are set. + + + + The action taken when extraction an entry would overwrite an + existing file is determined by the property. + + + + Within the call to Extract(), the content for the entry is + written into a filesystem file, and then the last modified time of the + file is set according to the property on + the entry. See the remarks the property for + some details about the last modified time. + + + + + + + Extract the entry to a file in the filesystem, using the specified + behavior when extraction would overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the file is set after + extraction. + + + + + The action to take if extraction would overwrite an existing file. + + + + + Extracts the entry to the specified stream. + + + + + The caller can specify any write-able stream, for example a , a , or ASP.NET's + Response.OutputStream. The content will be decrypted and + decompressed as necessary. If the entry is encrypted and no password + is provided, this method will throw. + + + The position on the stream is not reset by this method before it extracts. + You may want to call stream.Seek() before calling ZipEntry.Extract(). + + + + + the stream to which the entry should be extracted. + + + + + + Extract the entry to the filesystem, starting at the specified base + directory. + + + the pathname of the base directory + + + + + + This example extracts only the entries in a zip file that are .txt files, + into a directory called "textfiles". + + 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 + + + + + + + Using this method, existing entries in the filesystem will not be + overwritten. If you would like to force the overwrite of existing + files, see the property, or call + . + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified behavior when extraction would + overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + + + String sZipPath = "Airborne.zip"; + String sFilePath = "Readme.txt"; + String sRootFolder = "Digado"; + using (ZipFile zip = ZipFile.Read(sZipPath)) + { + if (zip.EntryFileNames.Contains(sFilePath)) + { + // use the string indexer on the zip file + zip[sFileName].Extract(sRootFolder, + ExtractExistingFileAction.OverwriteSilently); + } + } + + + + Dim sZipPath as String = "Airborne.zip" + Dim sFilePath As String = "Readme.txt" + Dim sRootFolder As String = "Digado" + Using zip As ZipFile = ZipFile.Read(sZipPath) + If zip.EntryFileNames.Contains(sFilePath) + ' use the string indexer on the zip file + zip(sFilePath).Extract(sRootFolder, _ + ExtractExistingFileAction.OverwriteSilently) + End If + End Using + + + + the pathname of the base directory + + The action to take if extraction would overwrite an existing file. + + + + + Extract the entry to the filesystem, using the current working directory + and the specified password. + + + + This method has a bunch of overloads! One of them is sure to be + the right one for you... + + + + + + + + + Existing entries in the filesystem will not be overwritten. If you + would like to force the overwrite of existing files, see the property, or call + . + + + + See the remarks on the property for some + details about how the "last modified" time of the created file is + set. + + + + + In this example, entries that use encryption are extracted using a + particular password. + + using (var zip = ZipFile.Read(FilePath)) + { + foreach (ZipEntry e in zip) + { + if (e.UsesEncryption) + e.ExtractWithPassword("Secret!"); + else + e.Extract(); + } + } + + + Using zip As ZipFile = ZipFile.Read(FilePath) + Dim e As ZipEntry + For Each e In zip + If (e.UsesEncryption) + e.ExtractWithPassword("Secret!") + Else + e.Extract + End If + Next + End Using + + + The Password to use for decrypting the entry. + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified password. + + + + + + + + Existing entries in the filesystem will not be overwritten. If you + would like to force the overwrite of existing files, see the property, or call + . + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + The pathname of the base directory. + The Password to use for decrypting the entry. + + + + Extract the entry to a file in the filesystem, relative to the + current directory, using the specified behavior when extraction + would overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + The Password to use for decrypting the entry. + + + The action to take if extraction would overwrite an existing file. + + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified behavior when extraction would + overwrite an existing file. + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + the pathname of the base directory + + The action to take if extraction would + overwrite an existing file. + + The Password to use for decrypting the entry. + + + + Extracts the entry to the specified stream, using the specified + Password. For example, the caller could extract to Console.Out, or + to a MemoryStream. + + + + + The caller can specify any write-able stream, for example a , a , or ASP.NET's + Response.OutputStream. The content will be decrypted and + decompressed as necessary. If the entry is encrypted and no password + is provided, this method will throw. + + + The position on the stream is not reset by this method before it extracts. + You may want to call stream.Seek() before calling ZipEntry.Extract(). + + + + + + the stream to which the entry should be extracted. + + + The password to use for decrypting the entry. + + + + + Opens a readable stream corresponding to the zip entry in the + archive. The stream decompresses and decrypts as necessary, as it + is read. + + + + + + DotNetZip offers a variety of ways to extract entries from a zip + file. This method allows an application to extract an entry by + reading a . + + + + The return value is of type . Use it as you would any + stream for reading. When an application calls on that stream, it will + receive data from the zip entry that is decrypted and decompressed + as necessary. + + + + CrcCalculatorStream adds one additional feature: it keeps a + CRC32 checksum on the bytes of the stream as it is read. The CRC + value is available in the property on the + CrcCalculatorStream. When the read is complete, your + application + should check this CRC against the + property on the ZipEntry to validate the content of the + ZipEntry. You don't have to validate the entry using the CRC, but + you should, to verify integrity. Check the example for how to do + this. + + + + If the entry is protected with a password, then you need to provide + a password prior to calling , either by + setting the property on the entry, or the + property on the ZipFile + itself. Or, you can use , the + overload of OpenReader that accepts a password parameter. + + + + If you want to extract entry data into a write-able stream that is + already opened, like a , do not + use this method. Instead, use . + + + + Your application may use only one stream created by OpenReader() at + a time, and you should not call other Extract methods before + completing your reads on a stream obtained from OpenReader(). This + is because there is really only one source stream for the compressed + content. A call to OpenReader() seeks in the source stream, to the + beginning of the compressed content. A subsequent call to + OpenReader() on a different entry will seek to a different position + in the source stream, as will a call to Extract() or one of its + overloads. This will corrupt the state for the decompressing stream + from the original call to OpenReader(). + + + + The OpenReader() method works only when the ZipEntry is + obtained from an instance of ZipFile. This method will throw + an exception if the ZipEntry is obtained from a . + + + + + This example shows how to open a zip archive, then read in a named + entry via a stream. After the read loop is complete, the code + compares the calculated during the read loop with the expected CRC + on the ZipEntry, to verify the extraction. + + using (ZipFile zip = new ZipFile(ZipFileToRead)) + { + ZipEntry e1= zip["Elevation.mp3"]; + using (Ionic.Zlib.CrcCalculatorStream s = e1.OpenReader()) + { + byte[] buffer = new byte[4096]; + int n, totalBytesRead= 0; + do { + n = s.Read(buffer,0, buffer.Length); + totalBytesRead+=n; + } while (n>0); + if (s.Crc32 != e1.Crc32) + throw new Exception(string.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32)); + if (totalBytesRead != e1.UncompressedSize) + throw new Exception(string.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize)); + } + } + + + Using zip As New ZipFile(ZipFileToRead) + Dim e1 As ZipEntry = zip.Item("Elevation.mp3") + Using s As Ionic.Zlib.CrcCalculatorStream = e1.OpenReader + Dim n As Integer + Dim buffer As Byte() = New Byte(4096) {} + Dim totalBytesRead As Integer = 0 + Do + n = s.Read(buffer, 0, buffer.Length) + totalBytesRead = (totalBytesRead + n) + Loop While (n > 0) + If (s.Crc32 <> e1.Crc32) Then + Throw New Exception(String.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32)) + End If + If (totalBytesRead <> e1.UncompressedSize) Then + Throw New Exception(String.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize)) + End If + End Using + End Using + + + + The Stream for reading. + + + + Opens a readable stream for an encrypted zip entry in the archive. + The stream decompresses and decrypts as necessary, as it is read. + + + + + See the documentation on the method for + full details. This overload allows the application to specify a + password for the ZipEntry to be read. + + + + The password to use for decrypting the entry. + The Stream for reading. + + + + Validates that the args are consistent. + + + Only one of {baseDir, outStream} can be non-null. + If baseDir is non-null, then the outputFile is created. + + + + + Default constructor. + + + Applications should never need to call this directly. It is exposed to + support COM Automation environments. + + + + + Sets the NTFS Creation, Access, and Modified times for the given entry. + + + + + When adding an entry from a file or directory, the Creation, Access, and + Modified times for the given entry are automatically set from the + filesystem values. When adding an entry from a stream or string, the + values are implicitly set to DateTime.Now. The application may wish to + set these values to some arbitrary value, before saving the archive, and + can do so using the various setters. If you want to set all of the times, + this method is more efficient. + + + + The values you set here will be retrievable with the , and properties. + + + + When this method is called, if both and are false, then the + EmitTimesInWindowsFormatWhenSaving flag is automatically set. + + + + DateTime values provided here without a DateTimeKind are assumed to be Local Time. + + + + the creation time of the entry. + the last access time of the entry. + the last modified time of the entry. + + + + + + + + + Provides a string representation of the instance. + a string representation of the instance. + + + + True if the referenced entry is a directory. + + + + + Provides a human-readable string with information about the ZipEntry. + + + + + The time and date at which the file indicated by the ZipEntry was + last modified. + + + + + The DotNetZip library sets the LastModified value for an entry, equal to + the Last Modified time of the file in the filesystem. If an entry is + added from a stream, the library uses System.DateTime.Now for this + value, for the given entry. + + + + This property allows the application to retrieve and possibly set the + LastModified value on an entry, to an arbitrary value. values with a + setting of DateTimeKind.Unspecified are taken to be expressed as + DateTimeKind.Local. + + + + Be aware that because of the way PKWare's + Zip specification describes how times are stored in the zip file, + the full precision of the System.DateTime datatype is not stored + for the last modified time when saving zip files. For more information on + how times are formatted, see the PKZip specification. + + + + The actual last modified time of a file can be stored in multiple ways in + the zip file, and they are not mutually exclusive: + + + + + In the so-called "DOS" format, which has a 2-second precision. Values + are rounded to the nearest even second. For example, if the time on the + file is 12:34:43, then it will be stored as 12:34:44. This first value + is accessible via the LastModified property. This value is always + present in the metadata for each zip entry. In some cases the value is + invalid, or zero. + + + + In the so-called "Windows" or "NTFS" format, as an 8-byte integer + quantity expressed as the number of 1/10 milliseconds (in other words + the number of 100 nanosecond units) since January 1, 1601 (UTC). This + format is how Windows represents file times. This time is accessible + via the ModifiedTime property. + + + + In the "Unix" format, a 4-byte quantity specifying the number of seconds since + January 1, 1970 UTC. + + + + In an older format, now deprecated but still used by some current + tools. This format is also a 4-byte quantity specifying the number of + seconds since January 1, 1970 UTC. + + + + + + Zip tools and libraries will always at least handle (read or write) the + DOS time, and may also handle the other time formats. Keep in mind that + while the names refer to particular operating systems, there is nothing in + the time formats themselves that prevents their use on other operating + systems. + + + + When reading ZIP files, the DotNetZip library reads the Windows-formatted + time, if it is stored in the entry, and sets both LastModified and + ModifiedTime to that value. When writing ZIP files, the DotNetZip + library by default will write both time quantities. It can also emit the + Unix-formatted time if desired (See .) + + + + The last modified time of the file created upon a call to + ZipEntry.Extract() may be adjusted during extraction to compensate + for differences in how the .NET Base Class Library deals with daylight + saving time (DST) versus how the Windows filesystem deals with daylight + saving time. Raymond Chen provides + some good context. + + + + In a nutshell: Daylight savings time rules change regularly. In 2007, for + example, the inception week of DST changed. In 1977, DST was in place all + year round. In 1945, likewise. And so on. Win32 does not attempt to + guess which time zone rules were in effect at the time in question. It + will render a time as "standard time" and allow the app to change to DST + as necessary. .NET makes a different choice. + + + + Compare the output of FileInfo.LastWriteTime.ToString("f") with what you + see in the Windows Explorer property sheet for a file that was last + written to on the other side of the DST transition. For example, suppose + the file was last modified on October 17, 2003, during DST but DST is not + currently in effect. Explorer's file properties reports Thursday, October + 17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17, + 2003, 9:45 AM. + + + + Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific + STANDARD Time. Even though October 17 of that year occurred during Pacific + Daylight Time, Win32 displays the time as standard time because that's + what time it is NOW. + + + + .NET BCL assumes that the current DST rules were in place at the time in + question. So, .NET says, "Well, if the rules in effect now were also in + effect on October 17, 2003, then that would be daylight time" so it + displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time. + + + + So .NET gives a value which is more intuitively correct, but is also + potentially incorrect, and which is not invertible. Win32 gives a value + which is intuitively incorrect, but is strictly correct. + + + + Because of this funkiness, this library adds one hour to the LastModified + time on the extracted file, if necessary. That is to say, if the time in + question had occurred in what the .NET Base Class Library assumed to be + DST. This assumption may be wrong given the constantly changing DST rules, + but it is the best we can do. + + + + + + + + Last Modified time for the file represented by the entry. + + + + + + This value corresponds to the "last modified" time in the NTFS file times + as described in the Zip + specification. When getting this property, the value may be + different from . When setting the property, + the property also gets set, but with a lower + precision. + + + + Let me explain. It's going to take a while, so get + comfortable. Originally, waaaaay back in 1989 when the ZIP specification + was originally described by the esteemed Mr. Phil Katz, the dominant + operating system of the time was MS-DOS. MSDOS stored file times with a + 2-second precision, because, c'mon, who is ever going to need better + resolution than THAT? And so ZIP files, regardless of the platform on + which the zip file was created, store file times in exactly the same format that DOS used + in 1989. + + + + Since then, the ZIP spec has evolved, but the internal format for file + timestamps remains the same. Despite the fact that the way times are + stored in a zip file is rooted in DOS heritage, any program on any + operating system can format a time in this way, and most zip tools and + libraries DO - they round file times to the nearest even second and store + it just like DOS did 25+ years ago. + + + + PKWare extended the ZIP specification to allow a zip file to store what + are called "NTFS Times" and "Unix(tm) times" for a file. These are the + last write, last access, and file creation + times of a particular file. These metadata are not actually specific + to NTFS or Unix. They are tracked for each file by NTFS and by various + Unix filesystems, but they are also tracked by other filesystems, too. + The key point is that the times are formatted in the zip file + in the same way that NTFS formats the time (ticks since win32 epoch), + or in the same way that Unix formats the time (seconds since Unix + epoch). As with the DOS time, any tool or library running on any + operating system is capable of formatting a time in one of these ways + and embedding it into the zip file. + + + + These extended times are higher precision quantities than the DOS time. + As described above, the (DOS) LastModified has a precision of 2 seconds. + The Unix time is stored with a precision of 1 second. The NTFS time is + stored with a precision of 0.0000001 seconds. The quantities are easily + convertible, except for the loss of precision you may incur. + + + + A zip archive can store the {C,A,M} times in NTFS format, in Unix format, + or not at all. Often a tool running on Unix or Mac will embed the times + in Unix format (1 second precision), while WinZip running on Windows might + embed the times in NTFS format (precision of of 0.0000001 seconds). When + reading a zip file with these "extended" times, in either format, + DotNetZip represents the values with the + ModifiedTime, AccessedTime and CreationTime + properties on the ZipEntry. + + + + While any zip application or library, regardless of the platform it + runs on, could use any of the time formats allowed by the ZIP + specification, not all zip tools or libraries do support all these + formats. Storing the higher-precision times for each entry is + optional for zip files, and many tools and libraries don't use the + higher precision quantities at all. The old DOS time, represented by + , is guaranteed to be present, though it + sometimes unset. + + + + Ok, getting back to the question about how the LastModified + property relates to this ModifiedTime + property... LastModified is always set, while + ModifiedTime is not. (The other times stored in the NTFS + times extension, CreationTime and AccessedTime also + may not be set on an entry that is read from an existing zip file.) + When reading a zip file, then LastModified takes the DOS time + that is stored with the file. If the DOS time has been stored as zero + in the zipfile, then this library will use DateTime.Now for the + LastModified value. If the ZIP file was created by an evolved + tool, then there will also be higher precision NTFS or Unix times in + the zip file. In that case, this library will read those times, and + set LastModified and ModifiedTime to the same value, the + one corresponding to the last write time of the file. If there are no + higher precision times stored for the entry, then ModifiedTime + remains unset (likewise AccessedTime and CreationTime), + and LastModified keeps its DOS time. + + + + When creating zip files with this library, by default the extended time + properties (ModifiedTime, AccessedTime, and + CreationTime) are set on the ZipEntry instance, and these data are + stored in the zip archive for each entry, in NTFS format. If you add an + entry from an actual filesystem file, then the entry gets the actual file + times for that file, to NTFS-level precision. If you add an entry from a + stream, or a string, then the times get the value DateTime.Now. In + this case LastModified and ModifiedTime will be identical, + to 2 seconds of precision. You can explicitly set the + CreationTime, AccessedTime, and ModifiedTime of an + entry using the property setters. If you want to set all of those + quantities, it's more efficient to use the method. Those + changes are not made permanent in the zip file until you call or one of its cousins. + + + + When creating a zip file, you can override the default behavior of + this library for formatting times in the zip file, disabling the + embedding of file times in NTFS format or enabling the storage of file + times in Unix format, or both. You may want to do this, for example, + when creating a zip file on Windows, that will be consumed on a Mac, + by an application that is not hip to the "NTFS times" format. To do + this, use the and + properties. A valid zip + file may store the file times in both formats. But, there are no + guarantees that a program running on Mac or Linux will gracefully + handle the NTFS-formatted times when Unix times are present, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. DotNetZip will always do something + reasonable; other libraries or tools may not. When in doubt, test. + + + + I'll bet you didn't think one person could type so much about time, eh? + And reading it was so enjoyable, too! Well, in appreciation, maybe you + should donate? + + + + + + + + + + + Last Access time for the file represented by the entry. + + + This value may or may not be meaningful. If the ZipEntry was read from an existing + Zip archive, this information may not be available. For an explanation of why, see + . + + + + + + + + The file creation time for the file represented by the entry. + + + + This value may or may not be meaningful. If the ZipEntry was read + from an existing zip archive, and the creation time was not set on the entry + when the zip file was created, then this property may be meaningless. For an + explanation of why, see . + + + + + + + + Specifies whether the Creation, Access, and Modified times for the given + entry will be emitted in "Windows format" when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entry should or should not be stored + in the zip archive in the format used by Windows. The default value of + this property is true. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified + () 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 . + + + + 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 Jan 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. + + + + Not all zip 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. Although the time values are + easily convertible, subject to a loss of precision, 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 , , and . + + + + This property is not mutually exclusive from the property. It is + possible that a zip entry can embed the timestamps in both forms, one + form, or neither. But, there are no guarantees that a program running on + Mac or Linux will gracefully handle NTFS Formatted times, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. When in doubt, test. + + + + Normally you will use the ZipFile.EmitTimesInWindowsFormatWhenSaving + property, to specify the behavior for all entries in a zip, rather than + the property on each individual entry. + + + + + + + + + + + + + Specifies whether the Creation, Access, and Modified times for the given + entry will be emitted in "Unix(tm) format" when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entry 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 (), Access (), and Modified + () 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 . + + + + 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 Jan 1, 1601 UTC. The other is a format Unix applications typically + use: seconds since Jan 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. + + + + 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. Although the time values are + easily convertible, subject to a loss of precision, 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 , , and . + + + + This property is not mutually exclusive from the property. It is + possible that a zip entry can embed the timestamps in both forms, one + form, or neither. But, there are no guarantees that a program running on + Mac or Linux will gracefully handle NTFS Formatted times, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. When in doubt, test. + + + + Normally you will use the ZipFile.EmitTimesInUnixFormatWhenSaving + property, to specify the behavior for all entries, rather than the + property on each individual entry. + + + + + + + + + + + + + The type of timestamp attached to the ZipEntry. + + + + This property is valid only for a ZipEntry that was read from a zip archive. + It indicates the type of timestamp attached to the entry. + + + + + + + + The file attributes for the entry. + + + + + + The attributes in NTFS include + ReadOnly, Archive, Hidden, System, and Indexed. When adding a + ZipEntry to a ZipFile, these attributes are set implicitly when + adding an entry from the filesystem. When adding an entry from a stream + or string, the Attributes are not set implicitly. Regardless of the way + an entry was added to a ZipFile, you can set the attributes + explicitly if you like. + + + + When reading a ZipEntry from a ZipFile, the attributes are + set according to the data stored in the ZipFile. If you extract the + entry from the archive to a filesystem file, DotNetZip will set the + attributes on the resulting file accordingly. + + + + The attributes can be set explicitly by the application. For example the + application may wish to set the FileAttributes.ReadOnly bit for all + entries added to an archive, so that on unpack, this attribute will be set + on the extracted file. Any changes you make to this property are made + permanent only when you call a Save() method on the ZipFile + instance that contains the ZipEntry. + + + + For example, an application may wish to zip up a directory and set the + ReadOnly bit on every file in the archive, so that upon later extraction, + the resulting files will be marked as ReadOnly. Not every extraction tool + respects these attributes, but if you unpack with DotNetZip, as for + example in a self-extracting archive, then the attributes will be set as + they are stored in the ZipFile. + + + + These attributes may not be interesting or useful if the resulting archive + is extracted on a non-Windows platform. How these attributes get used + upon extraction depends on the platform and tool used. + + + + This property is only partially supported in the Silverlight version + of the library: applications can read attributes on entries within + ZipFiles. But extracting entries within Silverlight will not set the + attributes on the extracted files. + + + + + + + The name of the filesystem file, referred to by the ZipEntry. + + + + + This property specifies the thing-to-be-zipped on disk, and is set only + when the ZipEntry is being created from a filesystem file. If the + ZipFile is instantiated by reading an existing .zip archive, then + the LocalFileName will be null (Nothing in VB). + + + + When it is set, the value of this property may be different than , which is the path used in the archive itself. If you + call Zip.AddFile("foop.txt", AlternativeDirectory), then the path + used for the ZipEntry within the zip archive will be different + than this path. + + + + If the entry is being added from a stream, then this is null (Nothing in VB). + + + + + + + + The name of the file contained in the ZipEntry. + + + + + + This is the name of the entry in the ZipFile itself. When creating + a zip archive, if the ZipEntry has been created from a filesystem + file, via a call to or , or a related overload, the value + of this property is derived from the name of that file. The + FileName property does not include drive letters, and may include a + different directory path, depending on the value of the + directoryPathInArchive parameter used when adding the entry into + the ZipFile. + + + + In some cases there is no related filesystem file - for example when a + ZipEntry is created using or one of the similar overloads. In this case, the value of + this property is derived from the fileName and the directory path passed + to that method. + + + + When reading a zip file, this property takes the value of the entry name + as stored in the zip file. If you extract such an entry, the extracted + file will take the name given by this property. + + + + Applications can set this property when creating new zip archives or when + reading existing archives. When setting this property, the actual value + that is set will replace backslashes with forward slashes, in accordance + with the Zip + specification, for compatibility with Unix(tm) and ... get + this.... Amiga! + + + + If an application reads a ZipFile via or a related overload, and then explicitly + sets the FileName on an entry contained within the ZipFile, and + then calls , the application will effectively + rename the entry within the zip archive. + + + + If an application sets the value of FileName, then calls + Extract() on the entry, the entry is extracted to a file using the + newly set value as the filename. The FileName value is made + permanent in the zip archive only after a call to one of the + ZipFile.Save() methods on the ZipFile that contains the + ZipEntry. + + + + If an application attempts to set the FileName to a value that + would result in a duplicate entry in the ZipFile, an exception is + thrown. + + + + When a ZipEntry is contained within a ZipFile, applications + cannot rename the entry within the context of a foreach (For + Each in VB) loop, because of the way the ZipFile stores + entries. If you need to enumerate through all the entries and rename one + or more of them, use ZipFile.EntriesSorted as the + collection. See also, ZipFile.GetEnumerator(). + + + + + + + The stream that provides content for the ZipEntry. + + + + + + The application can use this property to set the input stream for an + entry on a just-in-time basis. Imagine a scenario where the application + creates a ZipFile comprised of content obtained from hundreds of + files, via calls to AddFile(). The DotNetZip library opens streams + on these files on a just-in-time basis, only when writing the entry out to + an external store within the scope of a ZipFile.Save() call. Only + one input stream is opened at a time, as each entry is being written out. + + + + Now imagine a different application that creates a ZipFile + with content obtained from hundreds of streams, added through . Normally the + application would supply an open stream to that call. But when large + numbers of streams are being added, this can mean many open streams at one + time, unnecessarily. + + + + To avoid this, call and specify delegates that open and close the stream at + the time of Save. + + + + + Setting the value of this property when the entry was not added from a + stream (for example, when the ZipEntry was added with or , or when the entry was added by + reading an existing zip archive) will throw an exception. + + + + + + + + A flag indicating whether the InputStream was provided Just-in-time. + + + + + + When creating a zip archive, an application can obtain content for one or + more of the ZipEntry instances from streams, using the method. At the time + of calling that method, the application can supply null as the value of + the stream parameter. By doing so, the application indicates to the + library that it will provide a stream for the entry on a just-in-time + basis, at the time one of the ZipFile.Save() methods is called and + the data for the various entries are being compressed and written out. + + + + In this case, the application can set the + property, typically within the SaveProgress event (event type: ) for that entry. + + + + The application will later want to call Close() and Dispose() on that + stream. In the SaveProgress event, when the event type is , the application can + do so. This flag indicates that the stream has been provided by the + application on a just-in-time basis and that it is the application's + responsibility to call Close/Dispose on that stream. + + + + + + + + An enum indicating the source of the ZipEntry. + + + + + The version of the zip engine needed to read the ZipEntry. + + + + + This is a readonly property, indicating the version of the Zip + specification that the extracting tool or library must support to + extract the given entry. Generally higher versions indicate newer + features. Older zip engines obviously won't know about new features, and + won't be able to extract entries that depend on those newer features. + + + + + value + Features + + + + 20 + a basic Zip Entry, potentially using PKZIP encryption. + + + + + 45 + The ZIP64 extension is used on the entry. + + + + + 46 + File is compressed using BZIP2 compression* + + + + 50 + File is encrypted using PkWare's DES, 3DES, (broken) RC2 or RC4 + + + + 51 + File is encrypted using PKWare's AES encryption or corrected RC2 encryption. + + + + 52 + File is encrypted using corrected RC2-64 encryption** + + + + 61 + File is encrypted using non-OAEP key wrapping*** + + + + 63 + File is compressed using LZMA, PPMd+, Blowfish, or Twofish + + + + + + There are other values possible, not listed here. DotNetZip supports + regular PKZip encryption, and ZIP64 extensions. DotNetZip cannot extract + entries that require a zip engine higher than 45. + + + + This value is set upon reading an existing zip file, or after saving a zip + archive. + + + + + + The comment attached to the ZipEntry. + + + + + Each entry in a zip file can optionally have a comment associated to + it. The comment might be displayed by a zip tool during extraction, for + example. + + + + By default, the Comment is encoded in IBM437 code page. You can + specify an alternative with and + . + + + + + + + + Indicates whether the entry requires ZIP64 extensions. + + + + + + This property is null (Nothing in VB) until a Save() method on the + containing instance has been called. The property is + non-null (HasValue is true) only after a Save() method has + been called. + + + + After the containing ZipFile has been saved, the Value of this + property is true if any of the following three conditions holds: the + uncompressed size of the entry is larger than 0xFFFFFFFF; the compressed + size of the entry is larger than 0xFFFFFFFF; the relative offset of the + entry within the zip archive is larger than 0xFFFFFFFF. These quantities + are not known until a Save() is attempted on the zip archive and + the compression is applied. + + + + If none of the three conditions holds, then the Value is false. + + + + A Value of false does not indicate that the entry, as saved in the + zip archive, does not use ZIP64. It merely indicates that ZIP64 is + not required. An entry may use ZIP64 even when not required if + the property on the containing + ZipFile instance is set to , or if + the property on the containing + ZipFile instance is set to + and the output stream was not seekable. + + + + + + + + Indicates whether the entry actually used ZIP64 extensions, as it was most + recently written to the output file or stream. + + + + + + This Nullable property is null (Nothing in VB) until a Save() + method on the containing instance has been + called. HasValue is true only after a Save() method has been + called. + + + + The value of this property for a particular ZipEntry may change + over successive calls to Save() methods on the containing ZipFile, + even if the file that corresponds to the ZipEntry does not. This + may happen if other entries contained in the ZipFile expand, + causing the offset for this particular entry to exceed 0xFFFFFFFF. + + + + + + + The bitfield for the entry as defined in the zip spec. You probably + never need to look at this. + + + + + You probably do not need to concern yourself with the contents of this + property, but in case you do: + + + + + bit + meaning + + + + 0 + set if encryption is used. + + + + 1-2 + + set to determine whether normal, max, fast deflation. DotNetZip library + always leaves these bits unset when writing (indicating "normal" + deflation"), but can read an entry with any value here. + + + + + 3 + + Indicates that the Crc32, Compressed and Uncompressed sizes are zero in the + local header. This bit gets set on an entry during writing a zip file, when + it is saved to a non-seekable output stream. + + + + + + 4 + reserved for "enhanced deflating". This library doesn't do enhanced deflating. + + + + 5 + set to indicate the zip is compressed patched data. This library doesn't do that. + + + + 6 + + set if PKWare's strong encryption is used (must also set bit 1 if bit 6 is + set). This bit is not set if WinZip's AES encryption is set. + + + + 7 + not used + + + + 8 + not used + + + + 9 + not used + + + + 10 + not used + + + + 11 + + Language encoding flag (EFS). If this bit is set, the filename and comment + fields for this file must be encoded using UTF-8. This library currently + does not support UTF-8. + + + + + 12 + Reserved by PKWARE for enhanced compression. + + + + 13 + + Used when encrypting the Central Directory to indicate selected data + values in the Local Header are masked to hide their actual values. See + the section in the Zip + specification describing the Strong Encryption Specification for + details. + + + + + 14 + Reserved by PKWARE. + + + + 15 + Reserved by PKWARE. + + + + + + + + + The compression method employed for this ZipEntry. + + + + + + The + Zip specification allows a variety of compression methods. This + library supports just two: 0x08 = Deflate. 0x00 = Store (no compression), + for reading or writing. + + + + When reading an entry from an existing zipfile, the value you retrieve + here indicates the compression method used on the entry by the original + creator of the zip. When writing a zipfile, you can specify either 0x08 + (Deflate) or 0x00 (None). If you try setting something else, you will get + an exception. + + + + You may wish to set CompressionMethod to CompressionMethod.None (0) + when zipping already-compressed data like a jpg, png, or mp3 file. + This can save time and cpu cycles. + + + + When setting this property on a ZipEntry that is read from an + existing zip file, calling ZipFile.Save() will cause the new + CompressionMethod to be used on the entry in the newly saved zip file. + + + + Setting this property may have the side effect of modifying the + CompressionLevel property. If you set the CompressionMethod to a + value other than None, and CompressionLevel is previously + set to None, then CompressionLevel will be set to + Default. + + + + + + + In this example, the first entry added to the zip archive uses the default + behavior - compression is used where it makes sense. The second entry, + the MP3 file, is added to the archive without being compressed. + + using (ZipFile zip = new ZipFile(ZipFileToCreate)) + { + ZipEntry e1= zip.AddFile(@"notes\Readme.txt"); + ZipEntry e2= zip.AddFile(@"music\StopThisTrain.mp3"); + e2.CompressionMethod = CompressionMethod.None; + zip.Save(); + } + + + + Using zip As New ZipFile(ZipFileToCreate) + zip.AddFile("notes\Readme.txt") + Dim e2 as ZipEntry = zip.AddFile("music\StopThisTrain.mp3") + e2.CompressionMethod = CompressionMethod.None + zip.Save + End Using + + + + + + Sets the compression level to be used for the entry when saving the zip + archive. This applies only for CompressionMethod = DEFLATE. + + + + + When using the DEFLATE compression method, Varying the compression + level used on entries can affect the size-vs-speed tradeoff when + compression and decompressing data streams or files. + + + + 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. + + + + When setting this property on a ZipEntry that is read from an + existing zip file, calling ZipFile.Save() will cause the new + CompressionLevel to be used on the entry in the newly saved zip file. + + + + Setting this property may have the side effect of modifying the + CompressionMethod property. If you set the CompressionLevel + to a value other than None, CompressionMethod will be set + to Deflate, if it was previously None. + + + + Setting this property has no effect if the CompressionMethod is something + other than Deflate or None. + + + + + + + + The compressed size of the file, in bytes, within the zip archive. + + + + When reading a ZipFile, this value is read in from the existing + zip file. When creating or updating a ZipFile, the compressed + size is computed during compression. Therefore the value on a + ZipEntry is valid after a call to Save() (or one of its + overloads) in that case. + + + + + + + The size of the file, in bytes, before compression, or after extraction. + + + + When reading a ZipFile, this value is read in from the existing + zip file. When creating or updating a ZipFile, the uncompressed + size is computed during compression. Therefore the value on a + ZipEntry is valid after a call to Save() (or one of its + overloads) in that case. + + + + + + + The ratio of compressed size to uncompressed size of the ZipEntry. + + + + + This is a ratio of the compressed size to the uncompressed size of the + entry, expressed as a double in the range of 0 to 100+. A value of 100 + indicates no compression at all. It could be higher than 100 when the + compression algorithm actually inflates the data, as may occur for small + files, or uncompressible data that is encrypted. + + + + You could format it for presentation to a user via a format string of + "{3,5:F0}%" to see it as a percentage. + + + + If the size of the original uncompressed file is 0, implying a + denominator of 0, the return value will be zero. + + + + This property is valid after reading in an existing zip file, or after + saving the ZipFile that contains the ZipEntry. You cannot know the + effect of a compression transform until you try it. + + + + + + + The 32-bit CRC (Cyclic Redundancy Check) on the contents of the ZipEntry. + + + + + You probably don't need to concern yourself with this. It is used + internally by DotNetZip to verify files or streams upon extraction. + + The value is a 32-bit + CRC using 0xEDB88320 for the polynomial. This is the same CRC-32 used in + PNG, MPEG-2, and other protocols and formats. It is a read-only property; when + creating a Zip archive, the CRC for each entry is set only after a call to + Save() on the containing ZipFile. When reading an existing zip file, the value + of this property reflects the stored CRC for the entry. + + + + + + True if the entry is a directory (not a file). + This is a readonly property on the entry. + + + + + A derived property that is true if the entry uses encryption. + + + + + This is a readonly property on the entry. When reading a zip file, + the value for the ZipEntry is determined by the data read + from the zip file. After saving a ZipFile, the value of this + property for each ZipEntry indicates whether encryption was + actually used (which will have been true if the was set and the property + was something other than . + + + + + + Set this to specify which encryption algorithm to use for the entry when + saving it to a zip archive. + + + + + + Set this property in order to encrypt the entry when the ZipFile is + saved. When setting this property, you must also set a on the entry. If you set a value other than on this property and do not set a + Password then the entry will not be encrypted. The ZipEntry + data is encrypted as the ZipFile is saved, when you call or one of its cousins on the containing + ZipFile instance. You do not need to specify the Encryption + when extracting entries from an archive. + + + + The Zip specification from PKWare defines a set of encryption algorithms, + and the data formats for the zip archive that support them, and PKWare + supports those algorithms in the tools it produces. Other vendors of tools + and libraries, such as WinZip or Xceed, typically support a + subset of the algorithms specified by PKWare. These tools can + sometimes support additional different encryption algorithms and data + formats, not specified by PKWare. The AES Encryption specified and + supported by WinZip is the most popular example. This library supports a + subset of the complete set of algorithms specified by PKWare and other + vendors. + + + + There is no common, ubiquitous multi-vendor standard for strong encryption + within zip files. There is broad support for so-called "traditional" Zip + encryption, sometimes called Zip 2.0 encryption, as specified + by PKWare, but this encryption is considered weak and + breakable. This library currently supports the Zip 2.0 "weak" encryption, + and also a stronger WinZip-compatible AES encryption, using either 128-bit + or 256-bit key strength. If you want DotNetZip to support an algorithm + that is not currently supported, call the author of this library and maybe + we can talk business. + + + + The class also has a property. In most cases you will use + that property when setting encryption. This property takes + precedence over any Encryption set on the ZipFile itself. + Typically, you would use the per-entry Encryption when most entries in the + zip archive use one encryption algorithm, and a few entries use a + different one. If all entries in the zip file use the same Encryption, + then it is simpler to just set this property on the ZipFile itself, when + creating a zip archive. + + + + Some comments on updating archives: If you read a ZipFile, you can + modify the Encryption on an encrypted entry: you can remove encryption + from an entry that was encrypted; you can encrypt an entry that was not + encrypted previously; or, you can change the encryption algorithm. The + changes in encryption are not made permanent until you call Save() on the + ZipFile. To effect changes in encryption, the entry content is + streamed through several transformations, depending on the modification + the application has requested. For example if the entry is not encrypted + and the application sets Encryption to PkzipWeak, then at + the time of Save(), the original entry is read and decompressed, + then re-compressed and encrypted. Conversely, if the original entry is + encrypted with PkzipWeak encryption, and the application sets the + Encryption property to WinZipAes128, then at the time of + Save(), the original entry is decrypted via PKZIP encryption and + decompressed, then re-compressed and re-encrypted with AES. This all + happens automatically within the library, but it can be time-consuming for + large entries. + + + + Additionally, when updating archives, it is not possible to change the + password when changing the encryption algorithm. To change both the + algorithm and the password, you need to Save() the zipfile twice. First + set the Encryption to None, then call Save(). Then set the + Encryption to the new value (not "None"), then call Save() + once again. + + + + The WinZip AES encryption algorithms are not supported on the .NET Compact + Framework. + + + + + + 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 file + uses encryption. + + + // Create a zip archive with AES Encryption. + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("ReadMe.txt") + ZipEntry e1= zip.AddFile("2008-Regional-Sales-Report.pdf"); + e1.Encryption= EncryptionAlgorithm.WinZipAes256; + e1.Password= "Top.Secret.No.Peeking!"; + 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")) + { + // Specify the password that is used during extraction, for + // all entries that require a password: + zip.Password= "Top.Secret.No.Peeking!"; + zip.ExtractAll("extractDirectory"); + } + + + + ' Create a zip that uses Encryption. + Using zip As New ZipFile() + zip.AddFile("ReadMe.txt") + Dim e1 as ZipEntry + e1= zip.AddFile("2008-Regional-Sales-Report.pdf") + e1.Encryption= EncryptionAlgorithm.WinZipAes256 + e1.Password= "Top.Secret.No.Peeking!" + 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")) + ' Specify the password that is used during extraction, for + ' all entries that require a password: + zip.Password= "Top.Secret.No.Peeking!" + zip.ExtractAll("extractDirectory") + End Using + + + + + + Thrown in the setter if EncryptionAlgorithm.Unsupported is specified. + + + ZipEntry.Password + ZipFile.Encryption + + + + The Password to be used when encrypting a ZipEntry upon + ZipFile.Save(), or when decrypting an entry upon Extract(). + + + + + This is a write-only property on the entry. Set this to request that the + entry be encrypted when writing the zip archive, or set it to specify the + password to be used when extracting an existing entry that is encrypted. + + + + The password set here is implicitly used to encrypt the entry during the + operation, or to decrypt during the or operation. If you set + the Password on a ZipEntry after calling Save(), there is no + effect. + + + + Consider setting the property when using a + password. Answering concerns that the standard password protection + supported by all zip tools is weak, WinZip has extended the ZIP + specification with a way to use AES Encryption to protect entries in the + Zip file. Unlike the "PKZIP 2.0" encryption specified in the PKZIP + specification, AES + Encryption uses a standard, strong, tested, encryption + algorithm. DotNetZip can create zip archives that use WinZip-compatible + AES encryption, if you set the property. But, + archives created that use AES encryption may not be readable by all other + tools and libraries. For example, Windows Explorer cannot read a + "compressed folder" (a zip file) that uses AES encryption, though it can + read a zip file that uses "PKZIP encryption." + + + + The class also has a + property. This property takes precedence over any password set on the + ZipFile itself. 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. + + + + Some comments on updating archives: If you read a ZipFile, you + cannot modify the password on any encrypted entry, except by extracting + the entry with the original password (if any), removing the original entry + via , and then adding a new + entry with a new Password. + + + + For example, suppose you read a ZipFile, and there is an encrypted + entry. Setting the Password property on that ZipEntry and then + calling Save() on the ZipFile does not update the password + on that entry in the archive. Neither is an exception thrown. Instead, + what happens during the Save() is the existing entry is copied + through to the new zip archive, in its original encrypted form. Upon + re-reading that archive, the entry can be decrypted with its original + password. + + + + If you read a ZipFile, and there is an un-encrypted entry, you can set the + Password on the entry and then call Save() on the ZipFile, and get + encryption on that entry. + + + + + + + This example creates a zip file with two entries, and then extracts the + entries from the zip file. When creating the zip file, the two files are + added to the zip file using password protection. Each entry uses a + different password. During extraction, each file is extracted with the + appropriate password. + + + // create a file with encryption + using (ZipFile zip = new ZipFile()) + { + ZipEntry entry; + entry= zip.AddFile("Declaration.txt"); + entry.Password= "123456!"; + entry = zip.AddFile("Report.xls"); + entry.Password= "1Secret!"; + zip.Save("EncryptedArchive.zip"); + } + + // extract entries that use encryption + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + ZipEntry entry; + entry = zip["Declaration.txt"]; + entry.Password = "123456!"; + entry.Extract("extractDir"); + entry = zip["Report.xls"]; + entry.Password = "1Secret!"; + entry.Extract("extractDir"); + } + + + + + Using zip As New ZipFile + Dim entry as ZipEntry + entry= zip.AddFile("Declaration.txt") + entry.Password= "123456!" + entry = zip.AddFile("Report.xls") + entry.Password= "1Secret!" + zip.Save("EncryptedArchive.zip") + End Using + + + ' extract entries that use encryption + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + Dim entry as ZipEntry + entry = zip("Declaration.txt") + entry.Password = "123456!" + entry.Extract("extractDir") + entry = zip("Report.xls") + entry.Password = "1Secret!" + entry.Extract("extractDir") + End Using + + + + + + + ZipFile.Password + + + + The action the library should take when extracting a file that already exists. + + + + + 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. + + + + + + + This example shows how to set the ExtractExistingFile property in + an ExtractProgress event, in response to user input. The + ExtractProgress event is invoked if and only if the + ExtractExistingFile property was previously set to + ExtractExistingFileAction.InvokeExtractProgressEvent. + + public static void ExtractProgress(object sender, ExtractProgressEventArgs e) + { + if (e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) + Console.WriteLine("extract {0} ", e.CurrentEntry.FileName); + + else if (e.EventType == ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite) + { + ZipEntry entry = e.CurrentEntry; + string response = null; + // Ask the user if he wants overwrite the file + do + { + Console.Write("Overwrite {0} in {1} ? (y/n/C) ", entry.FileName, e.ExtractLocation); + response = Console.ReadLine(); + Console.WriteLine(); + + } while (response != null && response[0]!='Y' && + response[0]!='N' && response[0]!='C'); + + if (response[0]=='C') + e.Cancel = true; + else if (response[0]=='Y') + entry.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently; + else + entry.ExtractExistingFile= ExtractExistingFileAction.DoNotOverwrite; + } + } + + + + + + The action to take when an error is encountered while + opening or reading files as they are saved into a zip archive. + + + + + Errors can occur within a call to ZipFile.Save, as the various files contained + in a ZipFile are being saved into the zip archive. During the + Save, DotNetZip will perform a File.Open on the file + associated to the ZipEntry, and then will read the entire contents of + the file as it is zipped. Either the open or the Read may fail, because + of lock conflicts or other reasons. Using this property, you can + specify the action to take when such errors occur. + + + + Typically you will NOT set this property on individual ZipEntry + instances. Instead, you will set the ZipFile.ZipErrorAction property on + the ZipFile instance, before adding any entries to the + ZipFile. If you do this, errors encountered on behalf of any of + the entries in the ZipFile will be handled the same way. + + + + But, if you use a handler, you will want + to set this property on the ZipEntry within the handler, to + communicate back to DotNetZip what you would like to do with the + particular error. + + + + + + + + + Indicates whether the entry was included in the most recent save. + + + An entry can be excluded or skipped from a save if there is an error + opening or reading the entry. + + + + + + A callback that allows the application to specify the compression to use + for a given entry that is about to be added to the zip archive. + + + + + See + + + + + + Set to indicate whether to use UTF-8 encoding for filenames and comments. + + + + + + If this flag is set, the comment and filename for the entry will be + encoded with UTF-8, as described in the Zip + specification, if necessary. "Necessary" means, the filename or + entry comment (if any) cannot be reflexively encoded and decoded using the + default code page, IBM437. + + + + Setting this flag to true is equivalent to setting to System.Text.Encoding.UTF8. + + + + This flag has no effect or relation to the text encoding used within the + file itself. + + + + + + + The text encoding to use for the FileName and Comment on this ZipEntry, + when the default encoding is insufficient. + + + + + + Don't use this property. See . + + + + + + + Specifies the alternate text encoding used by this ZipEntry + + + + The default text encoding used in Zip files for encoding filenames and + comments is IBM437, which is something like a superset of ASCII. In + cases where this is insufficient, applications can specify an + alternate encoding. + + + When creating a zip file, the usage of the alternate encoding is + governed by the property. + Typically you would set both properties to tell DotNetZip to employ an + encoding that is not IBM437 in the zipfile you are creating. + + + Keep in mind that because the ZIP specification states that the only + valid encodings to use are IBM437 and UTF-8, if you use something + other than that, then zip tools and libraries may not be able to + successfully read the zip archive you generate. + + + The zip specification states that applications should presume that + IBM437 is in use, except when a special bit is set, which indicates + UTF-8. There is no way to specify an arbitrary code page, within the + zip file itself. When you create a zip file encoded with gb2312 or + ibm861 or anything other than IBM437 or UTF-8, then the application + that reads the zip file needs to "know" which code page to use. In + some cases, the code page used when reading is chosen implicitly. For + example, WinRar uses the ambient code page for the host desktop + operating system. The pitfall here is that if you create a zip in + Copenhagen and send it to Tokyo, the reader of the zipfile may not be + able to decode successfully. + + + + This example shows how to create a zipfile encoded with a + language-specific encoding: + + using (var zip = new ZipFile()) + { + zip.AlternateEnoding = System.Text.Encoding.GetEncoding("ibm861"); + zip.AlternateEnodingUsage = ZipOption.Always; + zip.AddFileS(arrayOfFiles); + zip.Save("Myarchive-Encoded-in-IBM861.zip"); + } + + + + + + + Describes if and when this instance should apply + AlternateEncoding to encode the FileName and Comment, when + saving. + + + + + + Indicates whether an entry is marked as a text file. Be careful when + using on this property. Unless you have a good reason, you should + probably ignore this property. + + + + + The ZIP format includes a provision for specifying whether an entry in + the zip archive is a text or binary file. This property exposes that + metadata item. Be careful when using this property: It's not clear + that this property as a firm meaning, across tools and libraries. + + + + To be clear, when reading a zip file, the property value may or may + not be set, and its value may or may not be valid. Not all entries + that you may think of as "text" entries will be so marked, and entries + marked as "text" are not guaranteed in any way to be text entries. + Whether the value is set and set correctly depends entirely on the + application that produced the zip file. + + + + There are many zip tools available, and when creating zip files, some + of them "respect" the IsText metadata field, and some of them do not. + Unfortunately, even when an application tries to do "the right thing", + it's not always clear what "the right thing" is. + + + + There's no firm definition of just what it means to be "a text file", + and the zip specification does not help in this regard. Twenty years + ago, text was ASCII, each byte was less than 127. IsText meant, all + bytes in the file were less than 127. These days, it is not the case + that all text files have all bytes less than 127. Any unicode file + may have bytes that are above 0x7f. The zip specification has nothing + to say on this topic. Therefore, it's not clear what IsText really + means. + + + + This property merely tells a reading application what is stored in the + metadata for an entry, without guaranteeing its validity or its + meaning. + + + + When DotNetZip is used to create a zipfile, it attempts to set this + field "correctly." For example, if a file ends in ".txt", this field + will be set. Your application may override that default setting. When + writing a zip file, you must set the property before calling + Save() on the ZipFile. + + + + When reading a zip file, a more general way to decide just what kind + of file is contained in a particular entry is to use the file type + database stored in the operating system. The operating system stores + a table that says, a file with .jpg extension is a JPG image file, a + file with a .xml extension is an XML document, a file with a .txt is a + pure ASCII text document, and so on. To get this information on + Windows, you + need to read and parse the registry. + + + + + using (var zip = new ZipFile()) + { + var e = zip.UpdateFile("Descriptions.mme", ""); + e.IsText = true; + zip.Save(zipPath); + } + + + + Using zip As New ZipFile + Dim e2 as ZipEntry = zip.AddFile("Descriptions.mme", "") + e.IsText= True + zip.Save(zipPath) + End Using + + + + + + Enumerates the options for a logical conjunction. This enum is intended for use + internally by the FileSelector class. + + + + + FileSelector encapsulates logic that selects files from a source - a zip file + or the filesystem - based on a set of criteria. This class is used internally + by the DotNetZip library, in particular for the AddSelectedFiles() methods. + This class can also be used independently of the zip capability in DotNetZip. + + + + + + The FileSelector class is used internally by the ZipFile class for selecting + files for inclusion into the ZipFile, when the method, or one of + its overloads, is called. It's also used for the methods. Typically, an + application that creates or manipulates Zip archives will not directly + interact with the FileSelector class. + + + + Some applications may wish to use the FileSelector class directly, to + select files from disk volumes based on a set of criteria, without creating or + querying Zip archives. The file selection criteria include: a pattern to + match the filename; the last modified, created, or last accessed time of the + file; the size of the file; and the attributes of the file. + + + + Consult the documentation for + for more information on specifying the selection criteria. + + + + + + + Constructor that allows the caller to specify file selection criteria. + + + + + This constructor allows the caller to specify a set of criteria for + selection of files. + + + + See for a description of + the syntax of the selectionCriteria string. + + + + By default the FileSelector will traverse NTFS Reparse Points. To + change this, use FileSelector(String, bool). + + + + The criteria for file selection. + + + + Constructor that allows the caller to specify file selection criteria. + + + + + This constructor allows the caller to specify a set of criteria for + selection of files. + + + + See for a description of + the syntax of the selectionCriteria string. + + + + The criteria for file selection. + + whether to traverse NTFS reparse points (junctions). + + + + + Returns a string representation of the FileSelector object. + + The string representation of the boolean logic statement of the file + selection criteria for this instance. + + + + Returns the names of the files in the specified directory + that fit the selection criteria specified in the FileSelector. + + + + This is equivalent to calling + with recurseDirectories = false. + + + + The name of the directory over which to apply the FileSelector + criteria. + + + + A collection of strings containing fully-qualified pathnames of files + that match the criteria specified in the FileSelector instance. + + + + + Returns the names of the files in the specified directory that fit the + selection criteria specified in the FileSelector, optionally recursing + through subdirectories. + + + + This method applies the file selection criteria contained in the + FileSelector to the files contained in the given directory, and + returns the names of files that conform to the criteria. + + + + The name of the directory over which to apply the FileSelector + criteria. + + + + Whether to recurse through subdirectories when applying the file + selection criteria. + + + + A collection of strings containing fully-qualified pathnames of files + that match the criteria specified in the FileSelector instance. + + + + + Retrieve the ZipEntry items in the ZipFile that conform to the specified criteria. + + + + + This method applies the criteria set in the FileSelector instance (as described in + the ) to the specified ZipFile. Using this + method, for example, you can retrieve all entries from the given ZipFile that + have filenames ending in .txt. + + + + Normally, applications would not call this method directly. This method is used + by the ZipFile class. + + + + Using the appropriate SelectionCriteria, you can retrieve entries based on size, + time, and attributes. See for a + description of the syntax of the SelectionCriteria string. + + + + + The ZipFile from which to retrieve entries. + + a collection of ZipEntry objects that conform to the criteria. + + + + Retrieve the ZipEntry items in the ZipFile that conform to the specified criteria. + + + + + This method applies the criteria set in the FileSelector instance (as described in + the ) to the specified ZipFile. Using this + method, for example, you can retrieve all entries from the given ZipFile that + have filenames ending in .txt. + + + + Normally, applications would not call this method directly. This method is used + by the ZipFile class. + + + + This overload allows the selection of ZipEntry instances from the ZipFile to be restricted + to entries contained within a particular directory in the ZipFile. + + + + Using the appropriate SelectionCriteria, you can retrieve entries based on size, + time, and attributes. See for a + description of the syntax of the SelectionCriteria string. + + + + + The ZipFile from which to retrieve entries. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + a collection of ZipEntry objects that conform to the criteria. + + + + The string specifying which files to include when retrieving. + + + + + 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", "type", and "name" nouns all 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,S,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. + + + + + ctime > 2009/01/01-03:00:00 + all files with a created time after 3am (local time), + on 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, and XOR. 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. Absent 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 "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". This "shorthand" notation does not work with compound + criteria. + + + + There is no logic in this class that insures that the 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 class does not check + for or detect such inconsistencies. + + + + + + Thrown in the setter if the value has an invalid syntax. + + + + + Indicates whether searches will traverse NTFS reparse points, like Junctions. + + + + + Summary description for EnumUtil. + + + + + Returns the value of the DescriptionAttribute if the specified Enum + value has one. If not, returns the ToString() representation of the + Enum value. + + The Enum to get the description for + + + + + Converts the string representation of the name or numeric value of one + or more enumerated constants to an equivalent enumerated object. + Note: use the DescriptionAttribute on enum values to enable this. + + The System.Type of the enumeration. + + A string containing the name or value to convert. + + + + + + Converts the string representation of the name or numeric value of one + or more enumerated constants to an equivalent enumerated object. A + parameter specified whether the operation is case-sensitive. Note: + use the DescriptionAttribute on enum values to enable this. + + The System.Type of the enumeration. + + A string containing the name or value to convert. + + + Whether the operation is case-sensitive or not. + + + + + An enum that provides the various encryption algorithms supported by this + library. + + + + + + PkzipWeak implies the use of Zip 2.0 encryption, which is known to be + weak and subvertible. + + + + A note on interoperability: Values of PkzipWeak and None are + specified in PKWARE's zip + specification, and are considered to be "standard". Zip archives + produced using these options will be interoperable with many other zip tools + and libraries, including Windows Explorer. + + + + Values of WinZipAes128 and WinZipAes256 are not part of the Zip + specification, but rather imply the use of a vendor-specific extension from + WinZip. If you want to produce interoperable Zip archives, do not use these + values. For example, if you produce a zip archive using WinZipAes256, you + will be able to open it in Windows Explorer on Windows XP and Vista, but you + will not be able to extract entries; trying this will lead to an "unspecified + error". For this reason, some people have said that a zip archive that uses + WinZip's AES encryption is not actually a zip archive at all. A zip archive + produced this way will be readable with the WinZip tool (Version 11 and + beyond). + + + + There are other third-party tools and libraries, both commercial and + otherwise, that support WinZip's AES encryption. These will be able to read + AES-encrypted zip archives produced by DotNetZip, and conversely applications + that use DotNetZip to read zip archives will be able to read AES-encrypted + archives produced by those tools or libraries. Consult the documentation for + those other tools and libraries to find out if WinZip's AES encryption is + supported. + + + + In case you care: According to the WinZip specification, the + actual AES key used is derived from the via an + algorithm that complies with RFC 2898, using an iteration + count of 1000. The algorithm is sometimes referred to as PBKDF2, which stands + for "Password Based Key Derivation Function #2". + + + + A word about password strength and length: The AES encryption technology is + very good, but any system is only as secure as the weakest link. If you want + to secure your data, be sure to use a password that is hard to guess. To make + it harder to guess (increase its "entropy"), you should make it longer. If + you use normal characters from an ASCII keyboard, a password of length 20 will + be strong enough that it will be impossible to guess. For more information on + that, I'd encourage you to read this + article. + + + + The WinZip AES algorithms are not supported with the version of DotNetZip that + runs on the .NET Compact Framework. This is because .NET CF lacks the + HMACSHA1 class that is required for producing the archive. + + + + + + No encryption at all. + + + + + Traditional or Classic pkzip encryption. + + + + + WinZip AES encryption (128 key bits). + + + + + WinZip AES encryption (256 key bits). + + + + + An encryption algorithm that is not supported by DotNetZip. + + + + + Encoder and Decoder for ZLIB and DEFLATE (IETF RFC1950 and RFC1951). + + + + This class compresses and decompresses data according to the Deflate algorithm + and optionally, the ZLIB format, as documented in RFC 1950 - ZLIB and RFC 1951 - DEFLATE. + + + + + The buffer from which data is taken. + + + + + An index into the InputBuffer array, indicating where to start reading. + + + + + The number of bytes available in the InputBuffer, starting at NextIn. + + + Generally you should set this to InputBuffer.Length before the first Inflate() or Deflate() call. + The class will update this number as calls to Inflate/Deflate are made. + + + + + Total number of bytes read so far, through all calls to Inflate()/Deflate(). + + + + + Buffer to store output data. + + + + + An index into the OutputBuffer array, indicating where to start writing. + + + + + The number of bytes available in the OutputBuffer, starting at NextOut. + + + Generally you should set this to OutputBuffer.Length before the first Inflate() or Deflate() call. + The class will update this number as calls to Inflate/Deflate are made. + + + + + Total number of bytes written to the output so far, through all calls to Inflate()/Deflate(). + + + + + used for diagnostics, when something goes wrong! + + + + + The compression level to use in this codec. Useful only in compression mode. + + + + + The number of Window Bits to use. + + + This gauges the size of the sliding window, and hence the + compression effectiveness as well as memory consumption. It's best to just leave this + setting alone if you don't know what it is. The maximum value is 15 bits, which implies + a 32k window. + + + + + The compression strategy to use. + + + This is only effective in compression. The theory offered by ZLIB is that different + strategies could potentially produce significant differences in compression behavior + for different data sets. Unfortunately I don't have any good recommendations for how + to set it differently. When I tested changing the strategy I got minimally different + compression performance. It's best to leave this property alone if you don't have a + good feel for it. Or, you may want to produce a test harness that runs through the + different strategy options and evaluates them on different file types. If you do that, + let me know your results. + + + + + Create a ZlibCodec. + + + If you use this default constructor, you will later have to explicitly call + InitializeInflate() or InitializeDeflate() before using the ZlibCodec to compress + or decompress. + + + + + Create a ZlibCodec that either compresses or decompresses. + + + Indicates whether the codec should compress (deflate) or decompress (inflate). + + + + + Initialize the inflation state. + + + It is not necessary to call this before using the ZlibCodec to inflate data; + It is implicitly called when you call the constructor. + + Z_OK if everything goes well. + + + + Initialize the inflation state with an explicit flag to + govern the handling of RFC1950 header bytes. + + + + By default, the ZLIB header defined in RFC 1950 is expected. If + you want to read a zlib stream you should specify true for + expectRfc1950Header. If you have a deflate stream, you will want to specify + false. It is only necessary to invoke this initializer explicitly if you + want to specify false. + + + whether to expect an RFC1950 header byte + pair when reading the stream of data to be inflated. + + Z_OK if everything goes well. + + + + Initialize the ZlibCodec for inflation, with the specified number of window bits. + + The number of window bits to use. If you need to ask what that is, + then you shouldn't be calling this initializer. + Z_OK if all goes well. + + + + Initialize the inflation state with an explicit flag to govern the handling of + RFC1950 header bytes. + + + + If you want to read a zlib stream you should specify true for + expectRfc1950Header. In this case, the library will expect to find a ZLIB + header, as defined in RFC + 1950, in the compressed stream. If you will be reading a DEFLATE or + GZIP stream, which does not have such a header, you will want to specify + false. + + + whether to expect an RFC1950 header byte pair when reading + the stream of data to be inflated. + The number of window bits to use. If you need to ask what that is, + then you shouldn't be calling this initializer. + Z_OK if everything goes well. + + + + Inflate the data in the InputBuffer, placing the result in the OutputBuffer. + + + You must have set InputBuffer and OutputBuffer, NextIn and NextOut, and AvailableBytesIn and + AvailableBytesOut before calling this method. + + + + private void InflateBuffer() + { + int bufferSize = 1024; + byte[] buffer = new byte[bufferSize]; + ZlibCodec decompressor = new ZlibCodec(); + + Console.WriteLine("\n============================================"); + Console.WriteLine("Size of Buffer to Inflate: {0} bytes.", CompressedBytes.Length); + MemoryStream ms = new MemoryStream(DecompressedBytes); + + int rc = decompressor.InitializeInflate(); + + decompressor.InputBuffer = CompressedBytes; + decompressor.NextIn = 0; + decompressor.AvailableBytesIn = CompressedBytes.Length; + + decompressor.OutputBuffer = buffer; + + // pass 1: inflate + do + { + decompressor.NextOut = 0; + decompressor.AvailableBytesOut = buffer.Length; + rc = decompressor.Inflate(FlushType.None); + + if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) + throw new Exception("inflating: " + decompressor.Message); + + ms.Write(decompressor.OutputBuffer, 0, buffer.Length - decompressor.AvailableBytesOut); + } + while (decompressor.AvailableBytesIn > 0 || decompressor.AvailableBytesOut == 0); + + // pass 2: finish and flush + do + { + decompressor.NextOut = 0; + decompressor.AvailableBytesOut = buffer.Length; + rc = decompressor.Inflate(FlushType.Finish); + + if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) + throw new Exception("inflating: " + decompressor.Message); + + if (buffer.Length - decompressor.AvailableBytesOut > 0) + ms.Write(buffer, 0, buffer.Length - decompressor.AvailableBytesOut); + } + while (decompressor.AvailableBytesIn > 0 || decompressor.AvailableBytesOut == 0); + + decompressor.EndInflate(); + } + + + + The flush to use when inflating. + Z_OK if everything goes well. + + + + Ends an inflation session. + + + Call this after successively calling Inflate(). This will cause all buffers to be flushed. + After calling this you cannot call Inflate() without a intervening call to one of the + InitializeInflate() overloads. + + Z_OK if everything goes well. + + + + I don't know what this does! + + Z_OK if everything goes well. + + + + Initialize the ZlibCodec for deflation operation. + + + The codec will use the MAX window bits and the default level of compression. + + + + int bufferSize = 40000; + byte[] CompressedBytes = new byte[bufferSize]; + byte[] DecompressedBytes = new byte[bufferSize]; + + ZlibCodec compressor = new ZlibCodec(); + + compressor.InitializeDeflate(CompressionLevel.Default); + + compressor.InputBuffer = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToCompress); + compressor.NextIn = 0; + compressor.AvailableBytesIn = compressor.InputBuffer.Length; + + compressor.OutputBuffer = CompressedBytes; + compressor.NextOut = 0; + compressor.AvailableBytesOut = CompressedBytes.Length; + + while (compressor.TotalBytesIn != TextToCompress.Length && compressor.TotalBytesOut < bufferSize) + { + compressor.Deflate(FlushType.None); + } + + while (true) + { + int rc= compressor.Deflate(FlushType.Finish); + if (rc == ZlibConstants.Z_STREAM_END) break; + } + + compressor.EndDeflate(); + + + + Z_OK if all goes well. You generally don't need to check the return code. + + + + Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel. + + + The codec will use the maximum window bits (15) and the specified + CompressionLevel. It will emit a ZLIB stream as it compresses. + + The compression level for the codec. + Z_OK if all goes well. + + + + Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel, + and the explicit flag governing whether to emit an RFC1950 header byte pair. + + + The codec will use the maximum window bits (15) and the specified CompressionLevel. + If you want to generate a zlib stream, you should specify true for + wantRfc1950Header. In this case, the library will emit a ZLIB + header, as defined in RFC + 1950, in the compressed stream. + + The compression level for the codec. + whether to emit an initial RFC1950 byte pair in the compressed stream. + Z_OK if all goes well. + + + + Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel, + and the specified number of window bits. + + + The codec will use the specified number of window bits and the specified CompressionLevel. + + The compression level for the codec. + the number of window bits to use. If you don't know what this means, don't use this method. + Z_OK if all goes well. + + + + Initialize the ZlibCodec for deflation operation, using the specified + CompressionLevel, the specified number of window bits, and the explicit flag + governing whether to emit an RFC1950 header byte pair. + + + The compression level for the codec. + whether to emit an initial RFC1950 byte pair in the compressed stream. + the number of window bits to use. If you don't know what this means, don't use this method. + Z_OK if all goes well. + + + + Deflate one batch of data. + + + You must have set InputBuffer and OutputBuffer before calling this method. + + + + private void DeflateBuffer(CompressionLevel level) + { + int bufferSize = 1024; + byte[] buffer = new byte[bufferSize]; + ZlibCodec compressor = new ZlibCodec(); + + Console.WriteLine("\n============================================"); + Console.WriteLine("Size of Buffer to Deflate: {0} bytes.", UncompressedBytes.Length); + MemoryStream ms = new MemoryStream(); + + int rc = compressor.InitializeDeflate(level); + + compressor.InputBuffer = UncompressedBytes; + compressor.NextIn = 0; + compressor.AvailableBytesIn = UncompressedBytes.Length; + + compressor.OutputBuffer = buffer; + + // pass 1: deflate + do + { + compressor.NextOut = 0; + compressor.AvailableBytesOut = buffer.Length; + rc = compressor.Deflate(FlushType.None); + + if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) + throw new Exception("deflating: " + compressor.Message); + + ms.Write(compressor.OutputBuffer, 0, buffer.Length - compressor.AvailableBytesOut); + } + while (compressor.AvailableBytesIn > 0 || compressor.AvailableBytesOut == 0); + + // pass 2: finish and flush + do + { + compressor.NextOut = 0; + compressor.AvailableBytesOut = buffer.Length; + rc = compressor.Deflate(FlushType.Finish); + + if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) + throw new Exception("deflating: " + compressor.Message); + + if (buffer.Length - compressor.AvailableBytesOut > 0) + ms.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut); + } + while (compressor.AvailableBytesIn > 0 || compressor.AvailableBytesOut == 0); + + compressor.EndDeflate(); + + ms.Seek(0, SeekOrigin.Begin); + CompressedBytes = new byte[compressor.TotalBytesOut]; + ms.Read(CompressedBytes, 0, CompressedBytes.Length); + } + + + whether to flush all data as you deflate. Generally you will want to + use Z_NO_FLUSH here, in a series of calls to Deflate(), and then call EndDeflate() to + flush everything. + + Z_OK if all goes well. + + + + End a deflation session. + + + Call this after making a series of one or more calls to Deflate(). All buffers are flushed. + + Z_OK if all goes well. + + + + Reset a codec for another deflation session. + + + Call this to reset the deflation state. For example if a thread is deflating + non-consecutive blocks, you can call Reset() after the Deflate(Sync) of the first + block and before the next Deflate(None) of the second block. + + Z_OK if all goes well. + + + + Set the CompressionStrategy and CompressionLevel for a deflation session. + + the level of compression to use. + the strategy to use for compression. + Z_OK if all goes well. + + + + Set the dictionary to be used for either Inflation or Deflation. + + The dictionary bytes to use. + Z_OK if all goes well. + + + + The Adler32 checksum on the data transferred through the codec so far. You probably don't need to look at this. + + + + + A class for collecting the various options that can be used when + Reading zip files for extraction or update. + + + + + When reading a zip file, there are several options an + application can set, to modify how the file is read, or what + the library does while reading. This class collects those + options into one container. + + + + Pass an instance of the ReadOptions class into the + ZipFile.Read() method. + + + . + . + + + + + An event handler for Read operations. When opening large zip + archives, you may want to display a progress bar or other + indicator of status progress while reading. This parameter + allows you to specify a ReadProgress Event Handler directly. + When you call Read(), the progress event is invoked as + necessary. + + + + + The System.IO.TextWriter to use for writing verbose status messages + during operations on 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, such as a System.IO.StringWriter. + + + + + The System.Text.Encoding to use when reading in the zip archive. Be + careful specifying the encoding. If the value you use here is not the same + as the Encoding used when the zip archive was created (possibly by a + different archiver) you will get unexpected results and possibly exceptions. + + + + + + + + Delegate in which the application writes the ZipEntry content for the named entry. + + + The name of the entry that must be written. + The stream to which the entry data should be written. + + + When you add an entry and specify a WriteDelegate, via , the application + code provides the logic that writes the entry data directly into the zip file. + + + + + This example shows how to define a WriteDelegate that obtains a DataSet, and then + writes the XML for the DataSet into the zip archive. There's no need to + save the XML to a disk file first. + + + private void WriteEntry (String filename, Stream output) + { + DataSet ds1 = ObtainDataSet(); + ds1.WriteXml(output); + } + + private void Run() + { + using (var zip = new ZipFile()) + { + zip.AddEntry(zipEntryName, WriteEntry); + zip.Save(zipFileName); + } + } + + + + Private Sub WriteEntry (ByVal filename As String, ByVal output As Stream) + DataSet ds1 = ObtainDataSet() + ds1.WriteXml(stream) + End Sub + + Public Sub Run() + Using zip = New ZipFile + zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry)) + zip.Save(zipFileName) + End Using + End Sub + + + + + + + Delegate in which the application opens the stream, just-in-time, for the named entry. + + + + The name of the ZipEntry that the application should open the stream for. + + + + When you add an entry via , the application code provides the logic that + opens and closes the stream for the given ZipEntry. + + + + + + + Delegate in which the application closes the stream, just-in-time, for the named entry. + + + + The name of the ZipEntry that the application should close the stream for. + + + The stream to be closed. + + + When you add an entry via , the application code provides the logic that + opens and closes the stream for the given ZipEntry. + + + + + + + Delegate for the callback by which the application tells the + library the CompressionLevel to use for a file. + + + + + Using this callback, the application can, for example, specify that + previously-compressed files (.mp3, .png, .docx, etc) should use a + CompressionLevel of None, or can set the compression level based + on any other factor. + + + + + + + In an EventArgs type, indicates which sort of progress event is being + reported. + + + There are events for reading, events for saving, and events for + extracting. This enumeration allows a single EventArgs type to be sued to + describe one of multiple subevents. For example, a SaveProgress event is + invoked before, after, and during the saving of a single entry. The value + of an enum with this type, specifies which event is being triggered. The + same applies to Extraction, Reading and Adding events. + + + + + Indicates that a Add() operation has started. + + + + + Indicates that an individual entry in the archive has been added. + + + + + Indicates that a Add() operation has completed. + + + + + Indicates that a Read() operation has started. + + + + + Indicates that an individual entry in the archive is about to be read. + + + + + Indicates that an individual entry in the archive has just been read. + + + + + Indicates that a Read() operation has completed. + + + + + The given event reports the number of bytes read so far + during a Read() operation. + + + + + Indicates that a Save() operation has started. + + + + + Indicates that an individual entry in the archive is about to be written. + + + + + Indicates that an individual entry in the archive has just been saved. + + + + + Indicates that a Save() operation has completed. + + + + + Indicates that the zip archive has been created in a + temporary location during a Save() operation. + + + + + Indicates that the temporary file is about to be renamed to the final archive + name during a Save() operation. + + + + + Indicates that the temporary file is has just been renamed to the final archive + name during a Save() operation. + + + + + Indicates that the self-extracting archive has been compiled + during a Save() operation. + + + + + The given event is reporting the number of source bytes that have run through the compressor so far + during a Save() operation. + + + + + Indicates that an entry is about to be extracted. + + + + + Indicates that an entry has just been extracted. + + + + + Indicates that extraction of an entry would overwrite an existing + filesystem file. You must use + + ExtractExistingFileAction.InvokeExtractProgressEvent in the call + to ZipEntry.Extract() in order to receive this event. + + + + + The given event is reporting the number of bytes written so far for + the current entry during an Extract() operation. + + + + + Indicates that an ExtractAll operation is about to begin. + + + + + Indicates that an ExtractAll operation has completed. + + + + + Indicates that an error has occurred while saving a zip file. + This generally means the file cannot be opened, because it has been + removed, or because it is locked by another process. It can also + mean that the file cannot be Read, because of a range lock conflict. + + + + + Provides information about the progress of a save, read, or extract operation. + This is a base class; you will probably use one of the classes derived from this one. + + + + + The total number of entries to be saved or extracted. + + + + + The name of the last entry saved or extracted. + + + + + In an event handler, set this to cancel the save or extract + operation that is in progress. + + + + + The type of event being reported. + + + + + Returns the archive name associated to this event. + + + + + The number of bytes read or written so far for this entry. + + + + + Total number of bytes that will be read or written for this entry. + This number will be -1 if the value cannot be determined. + + + + + Provides information about the progress of a Read operation. + + + + + Provides information about the progress of a Add operation. + + + + + Provides information about the progress of a save operation. + + + + + Constructor for the SaveProgressEventArgs. + + the name of the zip archive. + whether this is before saving the entry, or after + The total number of entries in the zip archive. + Number of entries that have been saved. + The entry involved in the event. + + + + Number of entries saved so far. + + + + + Provides information about the progress of the extract operation. + + + + + Constructor for the ExtractProgressEventArgs. + + the name of the zip archive. + whether this is before saving the entry, or after + The total number of entries in the zip archive. + Number of entries that have been extracted. + The entry involved in the event. + The location to which entries are extracted. + + + + Number of entries extracted so far. This is set only if the + EventType is Extracting_BeforeExtractEntry or Extracting_AfterExtractEntry, and + the Extract() is occurring witin the scope of a call to ExtractAll(). + + + + + Returns the extraction target location, a filesystem path. + + + + + Provides information about the an error that occurred while zipping. + + + + + Returns the exception that occurred, if any. + + + + + Returns the name of the file that caused the exception, if any. + + + + + Provides a stream metaphor for generating zip files. + + + + + This class 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 an alternative programming model to the one enabled by the + class. Use this when creating zip files, as an + alternative to the class, when you would like to use a + Stream type to write the zip file. + + + + 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 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. + + + + + ZipFile can be used to read and extract zip files, in addition to + creating zip files. ZipOutputStream cannot read zip files. If you want + to use a stream to read zip files, check out the class. + + + + ZipOutputStream does not support the creation of segmented or spanned + zip files. + + + + ZipOutputStream cannot produce a self-extracting archive. + + + + + Be aware that the ZipOutputStream class implements the interface. In order for + ZipOutputStream 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. + + + + Also, a note regarding compression performance: On the desktop .NET + Framework, DotNetZip can use a multi-threaded compression implementation + that provides significant speed increases on large files, over 300k or so, + at the cost of increased memory use at runtime. (The output of the + compression is almost exactly the same size). But, the multi-threaded + approach incurs a performance hit on smaller files. There's no way for the + ZipOutputStream to know whether parallel compression will be beneficial, + because the ZipOutputStream does not know how much data you will write + through the stream. You may wish to set the property to zero, if you are compressing + large files through ZipOutputStream. This will cause parallel + compression to be used, always. + + + + + + Create a ZipOutputStream, wrapping an existing stream. + + + + + The class is generally easier to use when creating + zip files. The ZipOutputStream offers a different metaphor for creating a + zip file, based on the class. + + + + + + The stream to wrap. It must be writable. This stream will be closed at + the time the ZipOutputStream is closed. + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + if (filesToZip.Count == 0) + { + System.Console.WriteLine("Nothing to do."); + return; + } + + using (var raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite )) + { + using (var output= new ZipOutputStream(raw)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + + foreach (string inputFileName in filesToZip) + { + System.Console.WriteLine("file: {0}", inputFileName); + + output.PutNextEntry(inputFileName); + using (var input = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Write )) + { + byte[] buffer= new byte[2048]; + int n; + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + } + + + + Private Sub Zipup() + Dim outputFileName As String = "XmlData.zip" + Dim filesToZip As String() = Directory.GetFiles(".", "*.xml") + If (filesToZip.Length = 0) Then + Console.WriteLine("Nothing to do.") + Else + Using raw As FileStream = File.Open(outputFileName, FileMode.Create, FileAccess.ReadWrite) + Using output As ZipOutputStream = New ZipOutputStream(raw) + output.Password = "VerySecret!" + output.Encryption = EncryptionAlgorithm.WinZipAes256 + Dim inputFileName As String + For Each inputFileName In filesToZip + Console.WriteLine("file: {0}", inputFileName) + output.PutNextEntry(inputFileName) + Using input As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + Dim n As Integer + Dim buffer As Byte() = New Byte(2048) {} + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + Next + End Using + End Using + End If + End Sub + + + + + + Create a ZipOutputStream that writes to a filesystem file. + + + + The class is generally easier to use when creating + zip files. The ZipOutputStream offers a different metaphor for creating a + zip file, based on the class. + + + + The name of the zip file to create. + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + if (filesToZip.Count == 0) + { + System.Console.WriteLine("Nothing to do."); + return; + } + + using (var output= new ZipOutputStream(outputFileName)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + + foreach (string inputFileName in filesToZip) + { + System.Console.WriteLine("file: {0}", inputFileName); + + output.PutNextEntry(inputFileName); + using (var input = File.Open(inputFileName, FileMode.Open, FileAccess.Read, + FileShare.Read | FileShare.Write )) + { + byte[] buffer= new byte[2048]; + int n; + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + Private Sub Zipup() + Dim outputFileName As String = "XmlData.zip" + Dim filesToZip As String() = Directory.GetFiles(".", "*.xml") + If (filesToZip.Length = 0) Then + Console.WriteLine("Nothing to do.") + Else + Using output As ZipOutputStream = New ZipOutputStream(outputFileName) + output.Password = "VerySecret!" + output.Encryption = EncryptionAlgorithm.WinZipAes256 + Dim inputFileName As String + For Each inputFileName In filesToZip + Console.WriteLine("file: {0}", inputFileName) + output.PutNextEntry(inputFileName) + Using input As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + Dim n As Integer + Dim buffer As Byte() = New Byte(2048) {} + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + Next + End Using + End If + End Sub + + + + + + Create a ZipOutputStream. + + + + See the documentation for the ZipOutputStream(Stream) + constructor for an example. + + + + The stream to wrap. It must be writable. + + + + true if the application would like the stream + to remain open after the ZipOutputStream has been closed. + + + + Provides a string representation of the instance. + + + This can be useful for debugging purposes. + + + a string representation of the instance. + + + + Returns true if an entry by the given name has already been written + to the ZipOutputStream. + + + + The name of the entry to scan for. + + + + true if an entry by the given name has already been written. + + + + + Write the data from the buffer to the stream. + + + + As the application writes data into this stream, the data may be + compressed and encrypted before being written out to the underlying + stream, depending on the settings of the + and the properties. + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Specify the name of the next entry that will be written to the zip file. + + + + + Call this method just before calling , to + specify the name of the entry that the next set of bytes written to + the ZipOutputStream belongs to. All subsequent calls to Write, + until the next call to PutNextEntry, + will be inserted into the named entry in the zip file. + + + + If the used in PutNextEntry() ends in + a slash, then the entry added is marked as a directory. Because directory + entries do not contain data, a call to Write(), before an + intervening additional call to PutNextEntry(), will throw an + exception. + + + + If you don't call Write() between two calls to + PutNextEntry(), the first entry is inserted into the zip file as a + file of zero size. This may be what you want. + + + + Because PutNextEntry() closes out the prior entry, if any, this + method may throw if there is a problem with the prior entry. + + + + This method returns the ZipEntry. You can modify public properties + on the ZipEntry, such as , , and so on, until the first call to + ZipOutputStream.Write(), or until the next call to + PutNextEntry(). If you modify the ZipEntry after + having called Write(), you may get a runtime exception, or you may + silently get an invalid zip archive. + + + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + using (FileStream fs raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite )) + { + using (var output= new ZipOutputStream(fs)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + output.PutNextEntry("entry1.txt"); + byte[] buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #1."); + output.Write(buffer,0,buffer.Length); + output.PutNextEntry("entry2.txt"); // this will be zero length + output.PutNextEntry("entry3.txt"); + buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #3."); + output.Write(buffer,0,buffer.Length); + } + } + } + + + + + The name of the entry to be added, including any path to be used + within the zip file. + + + + The ZipEntry created. + + + + + + Dispose the stream + + + + + This method writes the Zip Central directory, then closes the stream. The + application must call Dispose() (or Close) in order to produce a valid zip file. + + + + Typically the application will call Dispose() implicitly, via a using + statement in C#, or a Using statement in VB. + + + + + set this to true, always. + + + + This is a no-op. + + + + + This method always throws a NotSupportedException. + + ignored + ignored + ignored + nothing + + + + This method always throws a NotSupportedException. + + ignored + ignored + nothing + + + + This method always throws a NotSupportedException. + + ignored + + + + Sets the password to be used on the ZipOutputStream instance. + + + + + + When writing a zip archive, this password is applied to the entries, not + to the zip archive itself. It applies to any ZipEntry subsequently + written to the ZipOutputStream. + + + + Using a password does not encrypt or protect the "directory" of the + archive - the list of entries contained in the archive. 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. + + + + If you set this property, and then add a set of entries to the archive via + calls to PutNextEntry, 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. + + + + When setting the Password, you may also want to explicitly set the 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 , 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. + + + + Special case: if you wrap a ZipOutputStream around a non-seekable stream, + and use encryption, and emit an entry of zero bytes, the Close() or + PutNextEntry() following the entry will throw an exception. + + + + + + + The Encryption to use for entries added to the ZipOutputStream. + + + + + The specified Encryption is applied to the entries subsequently + written to the ZipOutputStream instance. + + + + If you set this to something other than + EncryptionAlgorithm.None, you will also need to set the + to a non-null, non-empty value in + order to actually get encryption on the entry. + + + + + ZipOutputStream.Password + ZipEntry.Encryption + + + + Size of the work buffer to use for the ZLIB codec during compression. + + + + Setting this may affect performance. For larger files, setting this to a + larger size may improve performance, but I'm not sure. Sorry, I don't + currently have good recommendations on how to set it. You can test it if + you like. + + + + + The compression strategy to use for all entries. + + + + Set the Strategy used by the ZLIB-compatible compressor, when compressing + data for the entries in the zip archive. 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 . + + + + + The type of timestamp attached to the ZipEntry. + + + + Set this in order to specify the kind of timestamp that should be emitted + into the zip file for each entry. + + + + + Sets the compression level to be used for entries subsequently added to + the zip archive. + + + + + 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 ZipOutputStream class, like , and , + setting this property on a ZipOutputStream + instance will cause the specified CompressionLevel to be used on all + items that are subsequently added to the + ZipOutputStream instance. + + + + 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. + + + + + + The compression method used on each entry added to the ZipOutputStream. + + + + + A comment attached to the zip archive. + + + + + + The application sets this property to specify a comment to be embedded + into the generated zip archive. + + + + 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 is + Never, it uses the default encoding (IBM437). (b) if is Always, it always uses the + alternate encoding (). (c) if 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(). + + + + + + + Specify whether to use ZIP64 extensions when saving a zip archive. + + + + + The default value for the property is . is + safest, in the sense that you will not get an Exception if a + pre-ZIP64 limit is exceeded. + + + + You must set this property before calling Write(). + + + + + + + Indicates whether ZIP64 extensions were used when saving the zip archive. + + + + The value is defined only after the ZipOutputStream has been closed. + + + + + Whether the ZipOutputStream should use case-insensitive comparisons when + checking for uniqueness of zip entries. + + + + + Though the zip specification doesn't prohibit zipfiles with duplicate + entries, Sane zip files have no duplicates, and the DotNetZip library + cannot create zip files with duplicate entries. If an application attempts + to call with a name that duplicates one + already used within the archive, the library will throw an Exception. + + + This property allows the application to specify whether the + ZipOutputStream instance considers ordinal case when checking for + uniqueness of zip entries. + + + + + + Indicates whether to encode entry filenames and entry comments using + Unicode (UTF-8). + + + + + 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, + the ZipOutputStream 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 ZipOutputStream, does not set the + encoding, 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, the zipfile will save properly, but extracting that file + later, with any zip tool, will result in an error, 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 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. + + + + + + + The text encoding to use when emitting entries into the zip archive, for + those entries whose filenames or comments cannot be encoded with the + default (IBM437) encoding. + + + + + 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 and 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 Close(). 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 + ZipOutputStream 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. 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. + + + + One possible approach 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 set + the property and reset + ProvisionalAlternateEncoding to IBM437 before calling Close(). + + + + + + A Text Encoding to use when encoding the filenames and comments for + all the ZipEntry items, during a ZipFile.Save() operation. + + + + Whether the encoding specified here is used during the save depends + on . + + + + + + 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. + + + + + The default text encoding used in zip archives. It is numeric 437, also + known as IBM437. + + + + + + The size threshold for an entry, above which a parallel deflate is used. + + + + + + DotNetZip will use multiple threads to compress any ZipEntry, when + the CompressionMethod is Deflate, and if the entry is + larger than the given size. Zero means "always use parallel + deflate", while -1 means "never use parallel deflate". + + + + If the entry size cannot be known before compression, as with any entry + added via a ZipOutputStream, 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 slightly less effective. + + + + Parallel deflate tends to not be as effective as single-threaded deflate + 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, and additional framing bytes must be added to the output + stream. For that reason, a deflated stream may be slightly larger when + compressed using parallel deflate, as compared to a traditional + single-threaded deflate. For files of about 512k, the increase over the + normal deflate is as much as 5% of the total compressed size. For larger + files, the difference 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 . You may have to perform + some tests to determine the best approach for your situation. + + + + The default value for this property is -1, which means parallel + compression will not be performed unless you set it to zero. + + + + + + + The maximum number of buffer pairs to use when performing + parallel compression. + + + + + 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 (). 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, but it is + effective only if set before calling + ZipOutputStream.Write() for the first time. + + + + + + + + + Always returns false. + + + + + Always returns false. + + + + + Always returns true. + + + + + Always returns a NotSupportedException. + + + + + Setting this property always returns a NotSupportedException. Getting it + returns the value of the Position on the underlying stream. + + + + + Provides a stream metaphor for reading zip files. + + + + + This class provides an alternative programming model for reading zip files to + the one enabled by the class. Use this when reading zip + files, as an alternative to the class, when you would + like to use a Stream class to read the file. + + + + Some application designs require a readable stream for input. This stream can + be used to read a zip file, and extract entries. + + + + Both the ZipInputStream class and the ZipFile class can be used + to read and extract zip files. Both of them support many of the common zip + features, including Unicode, different compression levels, and ZIP64. The + programming models differ. For example, when extracting entries via calls to + the GetNextEntry() and Read() methods on the + ZipInputStream class, the caller is responsible for creating the file, + writing the bytes into the file, setting the attributes on the file, and + setting the created, last modified, and last accessed timestamps on the + file. All of these things are done automatically by a call to ZipEntry.Extract(). For this reason, the + ZipInputStream is generally recommended for when your application wants + to extract the data, without storing that data into a file. + + + + Aside from the obvious differences in programming model, there are some + differences in capability between the ZipFile class and the + ZipInputStream class. + + + + + ZipFile can be used to create or update zip files, or read and + extract zip files. ZipInputStream can be used only to read and + extract zip files. If you want to use a stream to create zip files, check + out the . + + + + ZipInputStream cannot read segmented or spanned + zip files. + + + + ZipInputStream will not read Zip file comments. + + + + When reading larger files, ZipInputStream will always underperform + ZipFile. This is because the ZipInputStream does a full scan on the + zip file, while the ZipFile class reads the central directory of the + zip file. + + + + + + + + + Create a ZipInputStream, wrapping it around an existing stream. + + + + + + While the class is generally easier + to use, this class provides an alternative to those + applications that want to read from a zipfile directly, + using a . + + + + Both the ZipInputStream class and the ZipFile class can be used + to read and extract zip files. Both of them support many of the common zip + features, including Unicode, different compression levels, and ZIP64. The + programming models differ. For example, when extracting entries via calls to + the GetNextEntry() and Read() methods on the + ZipInputStream class, the caller is responsible for creating the file, + writing the bytes into the file, setting the attributes on the file, and + setting the created, last modified, and last accessed timestamps on the + file. All of these things are done automatically by a call to ZipEntry.Extract(). For this reason, the + ZipInputStream is generally recommended for when your application wants + to extract the data, without storing that data into a file. + + + + Aside from the obvious differences in programming model, there are some + differences in capability between the ZipFile class and the + ZipInputStream class. + + + + + ZipFile can be used to create or update zip files, or read and extract + zip files. ZipInputStream can be used only to read and extract zip + files. If you want to use a stream to create zip files, check out the . + + + + ZipInputStream cannot read segmented or spanned + zip files. + + + + ZipInputStream will not read Zip file comments. + + + + When reading larger files, ZipInputStream will always underperform + ZipFile. This is because the ZipInputStream does a full scan on the + zip file, while the ZipFile class reads the central directory of the + zip file. + + + + + + + + The stream to read. It must be readable. This stream will be closed at + the time the ZipInputStream is closed. + + + + + This example shows how to read a zip file, and extract entries, using the + ZipInputStream class. + + + private void Unzip() + { + byte[] buffer= new byte[2048]; + int n; + using (var raw = File.Open(inputFileName, FileMode.Open, FileAccess.Read)) + { + using (var input= new ZipInputStream(raw)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + if (e.IsDirectory) continue; + string outputPath = Path.Combine(extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + } + + + + Private Sub UnZip() + Dim inputFileName As String = "MyArchive.zip" + Dim extractDir As String = "extract" + Dim buffer As Byte() = New Byte(2048) {} + Using raw As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read) + Using input As ZipInputStream = New ZipInputStream(raw) + Dim e As ZipEntry + Do While (Not e = input.GetNextEntry Is Nothing) + If Not e.IsDirectory Then + Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _ + FileMode.Create, FileAccess.ReadWrite) + Dim n As Integer + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + End If + Loop + End Using + End Using + End Sub + + + + + + Create a ZipInputStream, given the name of an existing zip file. + + + + + + This constructor opens a FileStream for the given zipfile, and + wraps a ZipInputStream around that. See the documentation for the + constructor for full details. + + + + While the class is generally easier + to use, this class provides an alternative to those + applications that want to read from a zipfile directly, + using a . + + + + + + The name of the filesystem file to read. + + + + + This example shows how to read a zip file, and extract entries, using the + ZipInputStream class. + + + private void Unzip() + { + byte[] buffer= new byte[2048]; + int n; + using (var input= new ZipInputStream(inputFileName)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + if (e.IsDirectory) continue; + string outputPath = Path.Combine(extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + Private Sub UnZip() + Dim inputFileName As String = "MyArchive.zip" + Dim extractDir As String = "extract" + Dim buffer As Byte() = New Byte(2048) {} + Using input As ZipInputStream = New ZipInputStream(inputFileName) + Dim e As ZipEntry + Do While (Not e = input.GetNextEntry Is Nothing) + If Not e.IsDirectory Then + Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _ + FileMode.Create, FileAccess.ReadWrite) + Dim n As Integer + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + End If + Loop + End Using + End Sub + + + + + + Create a ZipInputStream, explicitly specifying whether to + keep the underlying stream open. + + + + See the documentation for the ZipInputStream(Stream) + constructor for a discussion of the class, and an example of how to use the class. + + + + The stream to read from. It must be readable. + + + + true if the application would like the stream + to remain open after the ZipInputStream has been closed. + + + + Provides a string representation of the instance. + + + This can be useful for debugging purposes. + + + a string representation of the instance. + + + + Read the data from the stream into the buffer. + + + + + The data for the zipentry will be decrypted and uncompressed, as + necessary, before being copied into the buffer. + + + + You must set the property before calling + Read() the first time for an encrypted entry. To determine if an + entry is encrypted and requires a password, check the ZipEntry.Encryption property. + + + + The buffer to hold the data read from the stream. + the offset within the buffer to copy the first byte read. + the number of bytes to read. + the number of bytes read, after decryption and decompression. + + + + Read the next entry from the zip file. + + + + + Call this method just before calling , + to position the pointer in the zip file to the next entry that can be + read. Subsequent calls to Read(), will decrypt and decompress the + data in the zip file, until Read() returns 0. + + + + Each time you call GetNextEntry(), the pointer in the wrapped + stream is moved to the next entry in the zip file. If you call , and thus re-position the pointer within + the file, you will need to call GetNextEntry() again, to insure + that the file pointer is positioned at the beginning of a zip entry. + + + + This method returns the ZipEntry. Using a stream approach, you will + read the raw bytes for an entry in a zip file via calls to Read(). + Alternatively, you can extract an entry into a file, or a stream, by + calling , or one of its siblings. + + + + + + The ZipEntry read. Returns null (or Nothing in VB) if there are no more + entries in the zip file. + + + + + + Dispose the stream. + + + + + This method disposes the ZipInputStream. It may also close the + underlying stream, depending on which constructor was used. + + + + Typically the application will call Dispose() implicitly, via + a using statement in C#, or a Using statement in VB. + + + + Application code won't call this code directly. This method may + be invoked in two distinct scenarios. If disposing == true, the + method has been called directly or indirectly by a user's code, + for example via the public Dispose() method. In this case, both + managed and unmanaged resources can be referenced and disposed. + If disposing == false, the method has been called by the runtime + from inside the object finalizer and this method should not + reference other objects; in that case only unmanaged resources + must be referenced or disposed. + + + + + true if the Dispose method was invoked by user code. + + + + + This is a no-op. + + + + + This method always throws a NotSupportedException. + + ignored + ignored + ignored + + + + This method seeks in the underlying stream. + + + + + Call this method if you want to seek around within the zip file for random access. + + + + Applications can intermix calls to Seek() with calls to . After a call to Seek(), + GetNextEntry() will get the next ZipEntry that falls after + the current position in the input stream. You're on your own for finding + out just where to seek in the stream, to get to the various entries. + + + + + the offset point to seek to + the reference point from which to seek + The new position + + + + This method always throws a NotSupportedException. + + ignored + + + + The text encoding to use when reading entries into the zip archive, for + those entries whose filenames or comments cannot be encoded with the + default (IBM437) encoding. + + + + + 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 read zip archives that use something other than + UTF-8 or IBM437, set this property to specify the code page to use when + reading encoded filenames and comments for each ZipEntry in the zip + file. + + + + This property is "provisional". When the entry in the zip archive is not + explicitly marked as using UTF-8, then IBM437 is used to decode filenames + and comments. If a loss of data would result from using IBM436 - + specifically when encoding and decoding is not reflexive - the codepage + specified here is used. It is possible, therefore, to have a given entry + with a Comment encoded in IBM437 and a FileName encoded with + the specified "provisional" codepage. + + + + When a zip file uses an arbitrary, non-UTF8 code page for encoding, there + is no standard way for the reader application - whether DotNetZip, WinZip, + WinRar, or something else - to know which codepage has been used for the + entries. 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. 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. + + + + + + + Size of the work buffer to use for the ZLIB codec during decompression. + + + + Setting this affects the performance and memory efficiency of compression + and decompression. For larger files, setting this to a larger size may + improve performance, but the exact numbers vary depending on available + memory, 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. + + + + + Sets the password to be used on the ZipInputStream instance. + + + + + + When reading a zip archive, this password is used to read and decrypt the + entries that are encrypted within the zip file. When entries within a zip + file use different passwords, set the appropriate password for the entry + before the first call to Read() for each entry. + + + + When reading an entry that is not encrypted, the value of this property is + ignored. + + + + + + + This example uses the ZipInputStream to read and extract entries from a + zip file, using a potentially different password for each entry. + + + byte[] buffer= new byte[2048]; + int n; + using (var raw = File.Open(_inputFileName, FileMode.Open, FileAccess.Read )) + { + using (var input= new ZipInputStream(raw)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + input.Password = PasswordForEntry(e.FileName); + if (e.IsDirectory) continue; + string outputPath = Path.Combine(_extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + + + + Always returns true. + + + + + Returns the value of CanSeek for the underlying (wrapped) stream. + + + + + Always returns false. + + + + + Returns the length of the underlying stream. + + + + + Gets or sets the position of the underlying stream. + + + Setting the position is equivalent to calling Seek(value, SeekOrigin.Begin). + + + + + This class implements the "traditional" or "classic" PKZip encryption, + which today is considered to be weak. On the other hand it is + ubiquitous. This class is intended for use only by the DotNetZip + library. + + + + Most uses of the DotNetZip library will not involve direct calls into + the ZipCrypto class. Instead, the ZipCrypto class is instantiated and + used by the ZipEntry() class when encryption or decryption on an entry + is employed. If for some reason you really wanted to use a weak + encryption algorithm in some other application, you might use this + library. But you would be much better off using one of the built-in + strong encryption libraries in the .NET Framework, like the AES + algorithm or SHA. + + + + + The default constructor for ZipCrypto. + + + + This class is intended for internal use by the library only. It's + probably not useful to you. Seriously. Stop reading this + documentation. It's a waste of your time. Go do something else. + Check the football scores. Go get an ice cream with a friend. + Seriously. + + + + + + Call this method on a cipher text to render the plaintext. You must + first initialize the cipher with a call to InitCipher. + + + + + var cipher = new ZipCrypto(); + cipher.InitCipher(Password); + // Decrypt the header. This has a side effect of "further initializing the + // encryption keys" in the traditional zip encryption. + byte[] DecryptedMessage = cipher.DecryptMessage(EncryptedMessage); + + + + The encrypted buffer. + + The number of bytes to encrypt. + Should be less than or equal to CipherText.Length. + + + The plaintext. + + + + This is the converse of DecryptMessage. It encrypts the plaintext + and produces a ciphertext. + + + The plain text buffer. + + + The number of bytes to encrypt. + Should be less than or equal to plainText.Length. + + + The ciphertext. + + + + This initializes the cipher with the given password. + See AppNote.txt for details. + + + + The passphrase for encrypting or decrypting with this cipher. + + + + + Step 1 - Initializing the encryption keys + ----------------------------------------- + Start with these keys: + Key(0) := 305419896 (0x12345678) + Key(1) := 591751049 (0x23456789) + Key(2) := 878082192 (0x34567890) + + Then, initialize the keys with a password: + + loop for i from 0 to length(password)-1 + update_keys(password(i)) + end loop + + Where update_keys() is defined as: + + update_keys(char): + Key(0) := crc32(key(0),char) + Key(1) := Key(1) + (Key(0) bitwiseAND 000000ffH) + Key(1) := Key(1) * 134775813 + 1 + Key(2) := crc32(key(2),key(1) rightshift 24) + end update_keys + + Where crc32(old_crc,char) is a routine that given a CRC value and a + character, returns an updated CRC value after applying the CRC-32 + algorithm described elsewhere in this document. + + + + + After the keys are initialized, then you can use the cipher to + encrypt the plaintext. + + + + Essentially we encrypt the password with the keys, then discard the + ciphertext for the password. This initializes the keys for later use. + + + + + + + From AppNote.txt: + unsigned char decrypt_byte() + local unsigned short temp + temp :=- Key(2) | 2 + decrypt_byte := (temp * (temp ^ 1)) bitshift-right 8 + end decrypt_byte + + + + + A Stream for reading and concurrently decrypting data from a zip file, + or for writing and concurrently encrypting data to a zip file. + + + + The constructor. + The underlying stream + To either encrypt or decrypt. + The pre-initialized ZipCrypto object. + + + + This is a helper class supporting WinZip AES encryption. + This class is intended for use only by the DotNetZip library. + + + + Most uses of the DotNetZip library will not involve direct calls into + the WinZipAesCrypto class. Instead, the WinZipAesCrypto class is + instantiated and used by the ZipEntry() class when WinZip AES + encryption or decryption on an entry is employed. + + + + + A stream that encrypts as it writes, or decrypts as it reads. The + Crypto is AES in CTR (counter) mode, which is compatible with the AES + encryption employed by WinZip 12.0. + + + + The AES/CTR encryption protocol used by WinZip works like this: + + - start with a counter, initialized to zero. + + - to encrypt, take the data by 16-byte blocks. For each block: + - apply the transform to the counter + - increement the counter + - XOR the result of the transform with the plaintext to + get the ciphertext. + - compute the mac on the encrypted bytes + - when finished with all blocks, store the computed MAC. + + - to decrypt, take the data by 16-byte blocks. For each block: + - compute the mac on the encrypted bytes, + - apply the transform to the counter + - increement the counter + - XOR the result of the transform with the ciphertext to + get the plaintext. + - when finished with all blocks, compare the computed MAC against + the stored MAC + + + + + + + The constructor. + + The underlying stream + To either encrypt or decrypt. + The pre-initialized WinZipAesCrypto object. + The maximum number of bytes to read from the stream. + + + + Close the stream. + + + + + Flush the content in the stream. + + + + + This method throws a NotImplementedException. + + + + + This method throws a NotImplementedException. + + + + + Returns the final HMAC-SHA1-80 for the data that was encrypted. + + + + + Returns true if the stream can be read. + + + + + Always returns false. + + + + + Returns true if the CryptoMode is Encrypt. + + + + + Getting this property throws a NotImplementedException. + + + + + Getting or Setting this property throws a NotImplementedException. + + + + + A class for compressing streams using the + Deflate algorithm with multiple threads. + + + + + This class performs DEFLATE compression through writing. For + more information on the Deflate algorithm, see IETF RFC 1951, + "DEFLATE Compressed Data Format Specification version 1.3." + + + + This class is similar to , except + that this class is for compression only, and this implementation uses an + approach that employs multiple worker threads to perform the DEFLATE. On + a multi-cpu or multi-core computer, the performance of this class can be + significantly higher than the single-threaded DeflateStream, particularly + for larger streams. How large? Anything over 10mb is a good candidate + for parallel compression. + + + + The tradeoff is that this class uses more memory and more CPU than the + vanilla DeflateStream, and also is less efficient as a compressor. For + large files the size of the compressed data stream can be less than 1% + larger than the size of a compressed data stream from the vanialla + DeflateStream. For smaller files the difference can be larger. The + difference will also be larger if you set the BufferSize to be lower than + the default value. Your mileage may vary. Finally, for small files, the + ParallelDeflateOutputStream can be much slower than the vanilla + DeflateStream, because of the overhead associated to using the thread + pool. + + + + + + + + Create a ParallelDeflateOutputStream. + + + + + This stream compresses data written into it via the DEFLATE + algorithm (see RFC 1951), and writes out the compressed byte stream. + + + + The instance will use the default compression level, the default + buffer sizes and the default number of threads and buffers per + thread. + + + + This class is similar to , + except that this implementation uses an approach that employs + multiple worker threads to perform the DEFLATE. On a multi-cpu or + multi-core computer, the performance of this class can be + significantly higher than the single-threaded DeflateStream, + particularly for larger streams. How large? Anything over 10mb is + a good candidate for parallel compression. + + + + + + + This example shows how to use a ParallelDeflateOutputStream to compress + data. It reads a file, compresses it, and writes the compressed data to + a second, output file. + + + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n= -1; + String outputFile = fileToCompress + ".compressed"; + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(outputFile)) + { + using (Stream compressor = new ParallelDeflateOutputStream(raw)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Dim outputFile As String = (fileToCompress & ".compressed") + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(outputFile) + Using compressor As Stream = New ParallelDeflateOutputStream(raw) + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + The stream to which compressed data will be written. + + + + Create a ParallelDeflateOutputStream using the specified CompressionLevel. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + + + Create a ParallelDeflateOutputStream and specify whether to leave the captive stream open + when the ParallelDeflateOutputStream is closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + + true if the application would like the stream to remain open after inflation/deflation. + + + + + Create a ParallelDeflateOutputStream and specify whether to leave the captive stream open + when the ParallelDeflateOutputStream is closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + true if the application would like the stream to remain open after inflation/deflation. + + + + + Create a ParallelDeflateOutputStream using the specified + CompressionLevel and CompressionStrategy, and specifying whether to + leave the captive stream open when the ParallelDeflateOutputStream is + closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + By tweaking this parameter, you may be able to optimize the compression for + data with particular characteristics. + + + true if the application would like the stream to remain open after inflation/deflation. + + + + + Write data to the stream. + + + + + + To use the ParallelDeflateOutputStream to compress data, create a + ParallelDeflateOutputStream with CompressionMode.Compress, passing a + writable output stream. Then call Write() on that + ParallelDeflateOutputStream, providing uncompressed data as input. The + data sent to the output stream will be the compressed form of the data + written. + + + + To decompress data, use the class. + + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Flush the stream. + + + + + Close the stream. + + + You must call Close on the stream to guarantee that all of the data written in has + been compressed, and the compressed data has been written out. + + + + Dispose the object + + + Because ParallelDeflateOutputStream is IDisposable, the + application must call this method when finished using the instance. + + + This method is generally called implicitly upon exit from + a using scope in C# (Using in VB). + + + + + The Dispose method + + indicates whether the Dispose method was invoked by user code. + + + + + Resets the stream for use with another stream. + + + Because the ParallelDeflateOutputStream is expensive to create, it + has been designed so that it can be recycled and re-used. You have + to call Close() on the stream first, then you can call Reset() on + it, to use it again on another stream. + + + + The new output stream for this era. + + + + + ParallelDeflateOutputStream deflater = null; + foreach (var inputFile in listOfFiles) + { + string outputFile = inputFile + ".compressed"; + using (System.IO.Stream input = System.IO.File.OpenRead(inputFile)) + { + using (var outStream = System.IO.File.Create(outputFile)) + { + if (deflater == null) + deflater = new ParallelDeflateOutputStream(outStream, + CompressionLevel.Best, + CompressionStrategy.Default, + true); + deflater.Reset(outStream); + + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + deflater.Write(buffer, 0, n); + } + } + } + } + + + + + + This method always throws a NotSupportedException. + + + The buffer into which data would be read, IF THIS METHOD + ACTUALLY DID ANYTHING. + + + The offset within that data array at which to insert the + data that is read, IF THIS METHOD ACTUALLY DID + ANYTHING. + + + The number of bytes to write, IF THIS METHOD ACTUALLY DID + ANYTHING. + + nothing. + + + + This method always throws a NotSupportedException. + + + The offset to seek to.... + IF THIS METHOD ACTUALLY DID ANYTHING. + + + The reference specifying how to apply the offset.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + nothing. It always throws. + + + + This method always throws a NotSupportedException. + + + The new value for the stream length.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + + + + The ZLIB strategy to be used during compression. + + + + + + The maximum number of buffer pairs to use. + + + + + This property sets an upper limit on the number of memory buffer + pairs to create. The implementation of this stream allocates + multiple buffers to facilitate parallel compression. As each buffer + fills up, this 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 (). 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, but it is effective + only before the first call to Write(), which is when the buffers are + allocated. + + + + + + The size of the buffers used by the compressor threads. + + + + + The default buffer size is 128k. The application can set this value + at any time, but it is effective only before the first Write(). + + + + Larger buffer sizes implies larger memory consumption but allows + more efficient compression. Using smaller buffer sizes consumes less + memory but may result in less effective compression. For example, + using the default buffer size of 128k, the compression delivered is + within 1% of the compression delivered by the single-threaded . On the other hand, using a + BufferSize of 8k can result in a compressed data stream that is 5% + larger than that delivered by the single-threaded + DeflateStream. Excessively small buffer sizes can also cause + the speed of the ParallelDeflateOutputStream to drop, because of + larger thread scheduling overhead dealing with many many small + buffers. + + + + The total amount of storage space allocated for buffering will be + (N*S*2), where N is the number of buffer pairs, and S is the size of + each buffer (this property). There are 2 buffers used by the + compressor, one for input and one for output. By default, DotNetZip + allocates 4 buffer pairs per CPU core, so if your machine has 4 + cores, then the number of buffer pairs used will be 16. If you + accept the default value of this property, 128k, then the + ParallelDeflateOutputStream will use 16 * 2 * 128kb of buffer memory + in total, or 4mb, in blocks of 128kb. If you set this property to + 64kb, then the number will be 16 * 2 * 64kb of buffer memory, or + 2mb. + + + + + + + The CRC32 for the data that was written out, prior to compression. + + + This value is meaningful only after a call to Close(). + + + + + The total number of uncompressed bytes processed by the ParallelDeflateOutputStream. + + + This value is meaningful only after a call to Close(). + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream supports Read operations. + + + Always returns false. + + + + + Indicates whether the stream supports Write operations. + + + Returns true if the provided stream is writable. + + + + + Reading this property always throws a NotSupportedException. + + + + + Returns the current position of the output stream. + + + + Because the output gets written by a background thread, + the value may change asynchronously. Setting this + property always throws a NotSupportedException. + + + + + + A read-only decorator stream that performs BZip2 decompression on Read. + + + + + Create a BZip2InputStream, wrapping it around the given input Stream. + + + + The input stream will be closed when the BZip2InputStream is closed. + + + The stream from which to read compressed data + + + + Create a BZip2InputStream with the given stream, and + specifying whether to leave the wrapped stream open when + the BZip2InputStream is closed. + + The stream from which to read compressed data + + Whether to leave the input stream open, when the BZip2InputStream closes. + + + + + This example reads a bzip2-compressed file, decompresses it, + and writes the decompressed data into a newly created file. + + + var fname = "logfile.log.bz2"; + using (var fs = File.OpenRead(fname)) + { + using (var decompressor = new Ionic.BZip2.BZip2InputStream(fs)) + { + var outFname = fname + ".decompressed"; + using (var output = File.Create(outFname)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = decompressor.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer, 0, n); + } + } + } + } + + + + + + Read data from the stream. + + + + + To decompress a BZip2 data stream, create a BZip2InputStream, + providing a stream that reads compressed data. Then call Read() on + that BZip2InputStream, and the data read will be decompressed + as you read. + + + + A BZip2InputStream can be used only for Read(), not for Write(). + + + + The buffer into which the read data should be placed. + the offset within that data array to put the first byte read. + the number of bytes to read. + the number of bytes actually read + + + + Read a single byte from the stream. + + the byte read from the stream, or -1 if EOF + + + + Flush the stream. + + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + + + + Dispose the stream. + + + indicates whether the Dispose method was invoked by user code. + + + + + Close the stream. + + + + + Read n bits from input, right justifying the result. + + + + For example, if you read 1 bit, the result is either 0 + or 1. + + + + The number of bits to read, always between 1 and 32. + + + + Called by createHuffmanDecodingTables() exclusively. + + + Called by recvDecodingTables() exclusively. + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes read in. + + + + + Compressor State + + + + Freq table collected to save a pass over the data during + decompression. + + + Initializes the tt array. + + This method is called when the required length of the array is known. + I don't initialize it at construction time to avoid unneccessary + memory allocation when compressing small files. + + + + A bunch of constants used in the Zlib interface. + + + + + The maximum number of window bits for the Deflate algorithm. + + + + + The default number of window bits for the Deflate algorithm. + + + + + indicates everything is A-OK + + + + + Indicates that the last operation reached the end of the stream. + + + + + The operation ended in need of a dictionary. + + + + + There was an error with the stream - not enough data, not open and readable, etc. + + + + + There was an error with the data - not enough data, bad data, etc. + + + + + There was an error with the working buffer. + + + + + The size of the working buffer used in the ZlibCodec class. Defaults to 8192 bytes. + + + + + The minimum size of the working buffer used in the ZlibCodec class. Currently it is 128 bytes. + + + + + An enum providing the options when an error occurs during opening or reading + of a file or directory that is being saved to a zip file. + + + + + This enum describes the actions that the library can take when an error occurs + opening or reading a file, as it is being saved into a Zip archive. + + + + In some cases an error will occur when DotNetZip tries to open a file to be + added to the zip archive. In other cases, an error might occur after the + file has been successfully opened, while DotNetZip is reading the file. + + + + The first problem might occur when calling AddDirectory() on a directory + that contains a Clipper .dbf file; the file is locked by Clipper and + cannot be opened by another process. An example of the second problem is + the ERROR_LOCK_VIOLATION that results when a file is opened by another + process, but not locked, and a range lock has been taken on the file. + Microsoft Outlook takes range locks on .PST files. + + + + + + Throw an exception when an error occurs while zipping. This is the default + behavior. (For COM clients, this is a 0 (zero).) + + + + + When an error occurs during zipping, for example a file cannot be opened, + skip the file causing the error, and continue zipping. (For COM clients, + this is a 1.) + + + + + When an error occurs during zipping, for example a file cannot be opened, + retry the operation that caused the error. Be careful with this option. If + the error is not temporary, the library will retry forever. (For COM + clients, this is a 2.) + + + + + When an error occurs, invoke the zipError event. The event type used is + . A typical use of this option: + a GUI application may wish to pop up a dialog to allow the user to view the + error that occurred, and choose an appropriate action. After your + processing in the error event, if you want to skip the file, set on the + ZipProgressEventArgs.CurrentEntry to Skip. If you want the + exception to be thrown, set ZipErrorAction on the CurrentEntry + to Throw. If you want to cancel the zip, set + ZipProgressEventArgs.Cancel to true. Cancelling differs from using + Skip in that a cancel will not save any further entries, if there are any. + (For COM clients, the value of this enum is a 3.) + + + + + Reset the BitWriter. + + + + This is useful when the BitWriter writes into a MemoryStream, and + is used by a BZip2Compressor, which itself is re-used for multiple + distinct data blocks. + + + + + + Write some number of bits from the given value, into the output. + + + + The nbits value should be a max of 25, for safety. For performance + reasons, this method does not check! + + + + + + Write a full 8-bit byte into the output. + + + + + Write four 8-bit bytes into the output. + + + + + Write all available byte-aligned bytes. + + + + This method writes no new output, but flushes any accumulated + bits. At completion, the accumulator may contain up to 7 + bits. + + + This is necessary when re-assembling output from N independent + compressors, one for each of N blocks. The output of any + particular compressor will in general have some fragment of a byte + remaining. This fragment needs to be accumulated into the + parent BZip2OutputStream. + + + + + + Writes all available bytes, and emits padding for the final byte as + necessary. This must be the last method invoked on an instance of + BitWriter. + + + + + Delivers the remaining bits, left-aligned, in a byte. + + + + This is valid only if NumRemainingBits is less than 8; + in other words it is valid only after a call to Flush(). + + + + + + An enum that provides the different self-extractor flavors + + + + + A self-extracting zip archive that runs from the console or + command line. + + + + + A self-extracting zip archive that presents a graphical user + interface when it is executed. + + + + + The options for generating a self-extracting archive. + + + + + The type of SFX to create. + + + + + The command to run after extraction. + + + + + This is optional. Leave it empty (null in C# or Nothing in + VB) to run no command after extraction. + + + + If it is non-empty, the SFX will execute the command specified in this + string on the user's machine, and using the extract directory as the + working directory for the process, after unpacking the archive. The + program to execute can include a path, if you like. If you want to execute + a program that accepts arguments, specify the program name, followed by a + space, and then the arguments for the program, each separated by a space, + just as you would on a normal command line. Example: program.exe arg1 + arg2. The string prior to the first space will be taken as the + program name, and the string following the first space specifies the + arguments to the program. + + + + If you want to execute a program that has a space in the name or path of + the file, surround the program name in double-quotes. The first character + of the command line should be a double-quote character, and there must be + a matching double-quote following the end of the program file name. Any + optional arguments to the program follow that, separated by + spaces. Example: "c:\project files\program name.exe" arg1 arg2. + + + + If the flavor of the SFX is SelfExtractorFlavor.ConsoleApplication, + then the SFX starts a new process, using this string as the post-extract + command line. The SFX waits for the process to exit. The exit code of + the post-extract command line is returned as the exit code of the + command-line self-extractor exe. A non-zero exit code is typically used to + indicated a failure by the program. In the case of an SFX, a non-zero exit + code may indicate a failure during extraction, OR, it may indicate a + failure of the run-after-extract program if specified, OR, it may indicate + the run-after-extract program could not be fuond. There is no way to + distinguish these conditions from the calling shell, aside from parsing + the output of the SFX. If you have Quiet set to true, you may not + see error messages, if a problem occurs. + + + + If the flavor of the SFX is + SelfExtractorFlavor.WinFormsApplication, then the SFX starts a new + process, using this string as the post-extract command line, and using the + extract directory as the working directory for the process. The SFX does + not wait for the command to complete, and does not check the exit code of + the program. If the run-after-extract program cannot be fuond, a message + box is displayed indicating that fact. + + + + You can specify environment variables within this string, with a format like + %NAME%. The value of these variables will be expanded at the time + the SFX is run. Example: %WINDIR%\system32\xcopy.exe may expand at + runtime to c:\Windows\System32\xcopy.exe. + + + + By combining this with the RemoveUnpackedFilesAfterExecute + flag, you can create an SFX that extracts itself, runs a file that + was extracted, then deletes all the files that were extracted. If + you want it to run "invisibly" then set Flavor to + SelfExtractorFlavor.ConsoleApplication, and set Quiet + to true. The user running such an EXE will see a console window + appear, then disappear quickly. You may also want to specify the + default extract location, with DefaultExtractDirectory. + + + + If you set Flavor to + SelfExtractorFlavor.WinFormsApplication, and set Quiet to + true, then a GUI with progressbars is displayed, but it is + "non-interactive" - it accepts no input from the user. Instead the SFX + just automatically unpacks and exits. + + + + + + + The default extract directory the user will see when + running the self-extracting archive. + + + + + Passing null (or Nothing in VB) here will cause the Self Extractor to use + the the user's personal directory () for the default extract + location. + + + + This is only a default location. The actual extract location will be + settable on the command line when the SFX is executed. + + + + You can specify environment variables within this string, + with %NAME%. The value of these variables will be + expanded at the time the SFX is run. Example: + %USERPROFILE%\Documents\unpack may expand at runtime to + c:\users\melvin\Documents\unpack. + + + + + + The name of an .ico file in the filesystem to use for the application icon + for the generated SFX. + + + + + Normally, DotNetZip will embed an "zipped folder" icon into the generated + SFX. If you prefer to use a different icon, you can specify it here. It + should be a .ico file. This file is passed as the /win32icon + option to the csc.exe compiler when constructing the SFX file. + + + + + + + Whether the ConsoleApplication SFX will be quiet during extraction. + + + + + This option affects the way the generated SFX runs. By default it is + false. When you set it to true,... + + + + + Flavor + Behavior + + + + ConsoleApplication + no messages will be emitted during successful + operation. Double-clicking the SFX in Windows + Explorer or as an attachment in an email will cause a console + window to appear briefly, before it disappears. If you run the + ConsoleApplication SFX from the cmd.exe prompt, it runs as a + normal console app; by default, because it is quiet, it displays + no messages to the console. If you pass the -v+ command line + argument to the Console SFX when you run it, you will get verbose + messages to the console. + + + + + WinFormsApplication + the SFX extracts automatically when the application + is launched, with no additional user input. + + + + + + + When you set it to false,... + + + + + Flavor + Behavior + + + + ConsoleApplication + the extractor will emit a + message to the console for each entry extracted. + + When double-clicking to launch the SFX, the console window will + remain, and the SFX will emit a message for each file as it + extracts. The messages fly by quickly, they won't be easily + readable, unless the extracted files are fairly large. + + + + + + WinFormsApplication + the SFX presents a forms UI and allows the user to select + options before extracting. + + + + + + + + + + Specify what the self-extractor will do when extracting an entry + would overwrite an existing file. + + + + The default behavvior is to Throw. + + + + + + Whether to remove the files that have been unpacked, after executing the + PostExtractCommandLine. + + + + + If true, and if there is a + PostExtractCommandLine, and if the command runs successfully, + then the files that the SFX unpacked will be removed, afterwards. If + the command does not complete successfully (non-zero return code), + that is interpreted as a failure, and the extracted files will not be + removed. + + + + Setting this flag, and setting Flavor to + SelfExtractorFlavor.ConsoleApplication, and setting Quiet to + true, results in an SFX that extracts itself, runs a file that was + extracted, then deletes all the files that were extracted, with no + intervention by the user. You may also want to specify the default + extract location, with DefaultExtractDirectory. + + + + + + + The file version number to embed into the generated EXE. It will show up, for + example, during a mouseover in Windows Explorer. + + + + + + The product version to embed into the generated EXE. It will show up, for + example, during a mouseover in Windows Explorer. + + + + You can use any arbitrary string, but a human-readable version number is + recommended. For example "v1.2 alpha" or "v4.2 RC2". If you specify nothing, + then there is no product version embedded into the EXE. + + + + + + The copyright notice, if any, to embed into the generated EXE. + + + + It will show up, for example, while viewing properties of the file in + Windows Explorer. You can use any arbitrary string, but typically you + want something like "Copyright © Dino Chiesa 2011". + + + + + + The description to embed into the generated EXE. + + + + Use any arbitrary string. This text will be displayed during a + mouseover in Windows Explorer. If you specify nothing, then the string + "DotNetZip SFX Archive" is embedded into the EXE as the description. + + + + + + The product name to embed into the generated EXE. + + + + Use any arbitrary string. This text will be displayed + while viewing properties of the EXE file in + Windows Explorer. + + + + + + The title to display in the Window of a GUI SFX, while it extracts. + + + + + By default the title show in the GUI window of a self-extractor + is "DotNetZip Self-extractor (http://DotNetZip.codeplex.com/)". + You can change that by setting this property before saving the SFX. + + + + This property has an effect only when producing a Self-extractor + of flavor SelfExtractorFlavor.WinFormsApplication. + + + + + + + Additional options for the csc.exe compiler, when producing the SFX + EXE. + + + + + + A class for compressing and decompressing GZIP streams. + + + + + The GZipStream is a Decorator on a + . It adds GZIP compression or decompression to any + stream. + + + + Like the System.IO.Compression.GZipStream in the .NET Base Class Library, the + Ionic.Zlib.GZipStream can compress while writing, or decompress while + reading, but not vice versa. The compression method used is GZIP, which is + documented in IETF RFC + 1952, "GZIP file format specification version 4.3". + + + A GZipStream can be used to decompress data (through Read()) or + to compress data (through Write()), but not both. + + + + If you wish to use the GZipStream to compress data, you must wrap it + around a write-able stream. As you call Write() on the GZipStream, the + data will be compressed into the GZIP format. If you want to decompress data, + you must wrap the GZipStream around a readable stream that contains an + IETF RFC 1952-compliant stream. The data will be decompressed as you call + Read() on the GZipStream. + + + + Though the GZIP format allows data from multiple files to be concatenated + together, this stream handles only a single segment of GZIP format, typically + representing a single file. + + + + This class is similar to and . + ZlibStream handles RFC1950-compliant streams. + handles RFC1951-compliant streams. This class handles RFC1952-compliant streams. + + + + + + + + + + The last modified time for the GZIP stream. + + + + GZIP allows the storage of a last modified time with each GZIP entry. + When compressing data, you can set this before the first call to + Write(). When decompressing, you can retrieve this value any time + after the first call to Read(). + + + + + Create a GZipStream using the specified CompressionMode. + + + + + When mode is CompressionMode.Compress, the GZipStream will use the + default compression level. + + + + As noted in the class documentation, the CompressionMode (Compress + or Decompress) also establishes the "direction" of the stream. A + GZipStream with CompressionMode.Compress works only through + Write(). A GZipStream with + CompressionMode.Decompress works only through Read(). + + + + + + This example shows how to use a GZipStream to compress data. + + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(outputFile)) + { + using (Stream compressor = new GZipStream(raw, CompressionMode.Compress)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n; + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + Dim outputFile As String = (fileToCompress & ".compressed") + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(outputFile) + Using compressor As Stream = New GZipStream(raw, CompressionMode.Compress) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + + + This example shows how to use a GZipStream to uncompress a file. + + private void GunZipFile(string filename) + { + if (!filename.EndsWith(".gz)) + throw new ArgumentException("filename"); + var DecompressedFile = filename.Substring(0,filename.Length-3); + byte[] working = new byte[WORKING_BUFFER_SIZE]; + int n= 1; + using (System.IO.Stream input = System.IO.File.OpenRead(filename)) + { + using (Stream decompressor= new Ionic.Zlib.GZipStream(input, CompressionMode.Decompress, true)) + { + using (var output = System.IO.File.Create(DecompressedFile)) + { + while (n !=0) + { + n= decompressor.Read(working, 0, working.Length); + if (n > 0) + { + output.Write(working, 0, n); + } + } + } + } + } + } + + + + Private Sub GunZipFile(ByVal filename as String) + If Not (filename.EndsWith(".gz)) Then + Throw New ArgumentException("filename") + End If + Dim DecompressedFile as String = filename.Substring(0,filename.Length-3) + Dim working(WORKING_BUFFER_SIZE) as Byte + Dim n As Integer = 1 + Using input As Stream = File.OpenRead(filename) + Using decompressor As Stream = new Ionic.Zlib.GZipStream(input, CompressionMode.Decompress, True) + Using output As Stream = File.Create(UncompressedFile) + Do + n= decompressor.Read(working, 0, working.Length) + If n > 0 Then + output.Write(working, 0, n) + End IF + Loop While (n > 0) + End Using + End Using + End Using + End Sub + + + + The stream which will be read or written. + Indicates whether the GZipStream will compress or decompress. + + + + Create a GZipStream using the specified CompressionMode and + the specified CompressionLevel. + + + + + The CompressionMode (Compress or Decompress) also establishes the + "direction" of the stream. A GZipStream with + CompressionMode.Compress works only through Write(). A + GZipStream with CompressionMode.Decompress works only + through Read(). + + + + + + + This example shows how to use a GZipStream to compress a file into a .gz file. + + + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(fileToCompress + ".gz")) + { + using (Stream compressor = new GZipStream(raw, + CompressionMode.Compress, + CompressionLevel.BestCompression)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n; + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(fileToCompress & ".gz") + Using compressor As Stream = New GZipStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + The stream to be read or written while deflating or inflating. + Indicates whether the GZipStream will compress or decompress. + A tuning knob to trade speed for effectiveness. + + + + Create a GZipStream using the specified CompressionMode, and + explicitly specify whether the stream should be left open after Deflation + or Inflation. + + + + + This constructor allows the application to request that the captive stream + remain open after the deflation or inflation occurs. By default, after + Close() is called on the stream, the captive stream is also + closed. In some cases this is not desired, for example if the stream is a + memory stream that will be re-read after compressed data has been written + to it. Specify true for the parameter to leave + the stream open. + + + + The (Compress or Decompress) also + establishes the "direction" of the stream. A GZipStream with + CompressionMode.Compress works only through Write(). A GZipStream + with CompressionMode.Decompress works only through Read(). + + + + The GZipStream will use the default compression level. If you want + to specify the compression level, see . + + + + See the other overloads of this constructor for example code. + + + + + + The stream which will be read or written. This is called the "captive" + stream in other places in this documentation. + + + Indicates whether the GZipStream will compress or decompress. + + + + true if the application would like the base stream to remain open after + inflation/deflation. + + + + + Create a GZipStream using the specified CompressionMode and the + specified CompressionLevel, and explicitly specify whether the + stream should be left open after Deflation or Inflation. + + + + + + This constructor allows the application to request that the captive stream + remain open after the deflation or inflation occurs. By default, after + Close() is called on the stream, the captive stream is also + closed. In some cases this is not desired, for example if the stream is a + memory stream that will be re-read after compressed data has been written + to it. Specify true for the parameter to + leave the stream open. + + + + As noted in the class documentation, the CompressionMode (Compress + or Decompress) also establishes the "direction" of the stream. A + GZipStream with CompressionMode.Compress works only through + Write(). A GZipStream with CompressionMode.Decompress works only + through Read(). + + + + + + This example shows how to use a GZipStream to compress data. + + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(outputFile)) + { + using (Stream compressor = new GZipStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression, true)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n; + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + Dim outputFile As String = (fileToCompress & ".compressed") + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(outputFile) + Using compressor As Stream = New GZipStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression, True) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + The stream which will be read or written. + Indicates whether the GZipStream will compress or decompress. + true if the application would like the stream to remain open after inflation/deflation. + A tuning knob to trade speed for effectiveness. + + + + Dispose the stream. + + + + This may or may not result in a Close() call on the captive + stream. See the constructors that have a leaveOpen parameter + for more information. + + + This method may be invoked in two distinct scenarios. If disposing + == true, the method has been called directly or indirectly by a + user's code, for example via the public Dispose() method. In this + case, both managed and unmanaged resources can be referenced and + disposed. If disposing == false, the method has been called by the + runtime from inside the object finalizer and this method should not + reference other objects; in that case only unmanaged resources must + be referenced or disposed. + + + + indicates whether the Dispose method was invoked by user code. + + + + + Flush the stream. + + + + + Read and decompress data from the source stream. + + + + With a GZipStream, decompression is done through reading. + + + + + byte[] working = new byte[WORKING_BUFFER_SIZE]; + using (System.IO.Stream input = System.IO.File.OpenRead(_CompressedFile)) + { + using (Stream decompressor= new Ionic.Zlib.GZipStream(input, CompressionMode.Decompress, true)) + { + using (var output = System.IO.File.Create(_DecompressedFile)) + { + int n; + while ((n= decompressor.Read(working, 0, working.Length)) !=0) + { + output.Write(working, 0, n); + } + } + } + } + + + The buffer into which the decompressed data should be placed. + the offset within that data array to put the first byte read. + the number of bytes to read. + the number of bytes actually read + + + + Calling this method always throws a . + + irrelevant; it will always throw! + irrelevant; it will always throw! + irrelevant! + + + + Calling this method always throws a . + + irrelevant; this method will always throw! + + + + Write data to the stream. + + + + + If you wish to use the GZipStream to compress data while writing, + you can create a GZipStream with CompressionMode.Compress, and a + writable output stream. Then call Write() on that GZipStream, + providing uncompressed data as input. The data sent to the output stream + will be the compressed form of the data written. + + + + A GZipStream can be used for Read() or Write(), but not + both. Writing implies compression. Reading implies decompression. + + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Compress a string into a byte array using GZip. + + + + Uncompress it with . + + + + + + + A string to compress. The string will first be encoded + using UTF8, then compressed. + + + The string in compressed form + + + + Compress a byte array into a new byte array using GZip. + + + + Uncompress it with . + + + + + + + A buffer to compress. + + + The data in compressed form + + + + Uncompress a GZip'ed byte array into a single string. + + + + + + + A buffer containing GZIP-compressed data. + + + The uncompressed string + + + + Uncompress a GZip'ed byte array into a byte array. + + + + + + + A buffer containing data that has been compressed with GZip. + + + The data in uncompressed form + + + + The comment on the GZIP stream. + + + + + The GZIP format allows for each file to optionally have an associated + comment stored with the file. The comment is encoded with the ISO-8859-1 + code page. To include a comment in a GZIP stream you create, set this + property before calling Write() for the first time on the + GZipStream. + + + + When using GZipStream to decompress, you can retrieve this property + after the first call to Read(). If no comment has been set in the + GZIP bytestream, the Comment property will return null + (Nothing in VB). + + + + + + The FileName for the GZIP stream. + + + + + + The GZIP format optionally allows each file to have an associated + filename. When compressing data (through Write()), set this + FileName before calling Write() the first time on the GZipStream. + The actual filename is encoded into the GZIP bytestream with the + ISO-8859-1 code page, according to RFC 1952. It is the application's + responsibility to insure that the FileName can be encoded and decoded + correctly with this code page. + + + + When decompressing (through Read()), you can retrieve this value + any time after the first Read(). In the case where there was no filename + encoded into the GZIP bytestream, the property will return null (Nothing + in VB). + + + + + + The CRC on the GZIP stream. + + + This is used for internal error checking. You probably don't need to look at this property. + + + + + This property sets the flush behavior on the stream. + + + + + The size of the working buffer for the compression codec. + + + + + The working buffer is used for all stream operations. The default size is + 1024 bytes. The minimum size is 128 bytes. You may get better performance + with a larger buffer. Then again, you might not. You would have to test + it. + + + + Set this before the first call to Read() or Write() on the + stream. If you try to set it afterwards, it will throw. + + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the total bytes + written out, if used in writing, or the total bytes read in, if used in + reading. The count may refer to compressed bytes or uncompressed bytes, + depending on how you've used the stream. + + + + Knuth's increments seem to work better than Incerpi-Sedgewick here. + Possibly because the number of elems to sort is usually small, typically + <= 20. + + + + BZip2Compressor writes its compressed data out via a BitWriter. This + is necessary because BZip2 does byte shredding. + + + + + Accept new bytes into the compressor data buffer + + + + This method does the first-level (cheap) run-length encoding, and + stores the encoded data into the rle block. + + + + + + Process one input byte into the block. + + + + + To "process" the byte means to do the run-length encoding. + There are 3 possible return values: + + 0 - the byte was not written, in other words, not + encoded into the block. This happens when the + byte b would require the start of a new run, and + the block has no more room for new runs. + + 1 - the byte was written, and the block is not full. + + 2 - the byte was written, and the block is full. + + + + 0 if the byte was not written, non-zero if written. + + + + Append one run to the output block. + + + + + This compressor does run-length-encoding before BWT and etc. This + method simply appends a run to the output block. The append always + succeeds. The return value indicates whether the block is full: + false (not full) implies that at least one additional run could be + processed. + + + true if the block is now full; otherwise false. + + + + Compress the data that has been placed (Run-length-encoded) into the + block. The compressed data goes into the CompressedBytes array. + + + + Side effects: 1. fills the CompressedBytes array. 2. sets the + AvailableBytesOut property. + + + + + This is the most hammered method of this class. + +

+ This is the version using unrolled loops. +

+
+ + Method "mainQSort3", file "blocksort.c", BZip2 1.0.2 + + + + The number of uncompressed bytes being held in the buffer. + + + + I am thinking this may be useful in a Stream that uses this + compressor class. In the Close() method on the stream it could + check this value to see if anything has been written at all. You + may think the stream could easily track the number of bytes it + wrote, which would eliminate the need for this. But, there is the + case where the stream writes a complete block, and it is full, and + then writes no more. In that case the stream may want to check. + + + + + Array instance identical to sfmap, both are used only + temporarily and independently, so we do not need to allocate + additional memory. + + + + An enum for the options when extracting an entry would overwrite an existing file. + + + + + This enum describes the actions that the library can take when an + Extract() or ExtractWithPassword() method is called to extract an + entry to a filesystem, and the extraction would overwrite an existing filesystem + file. + + + + + + + Throw an exception when extraction would overwrite an existing file. (For + COM clients, this is a 0 (zero).) + + + + + When extraction would overwrite an existing file, overwrite the file silently. + The overwrite will happen even if the target file is marked as read-only. + (For COM clients, this is a 1.) + + + + + When extraction would overwrite an existing file, don't overwrite the file, silently. + (For COM clients, this is a 2.) + + + + + When extraction would overwrite an existing file, invoke the ExtractProgress + event, using an event type of . In + this way, the application can decide, just-in-time, whether to overwrite the + file. For example, a GUI application may wish to pop up a dialog to allow + the user to choose. You may want to examine the property before making + the decision. If, after your processing in the Extract progress event, you + want to NOT extract the file, set + on the ZipProgressEventArgs.CurrentEntry to DoNotOverwrite. + If you do want to extract the file, set ZipEntry.ExtractExistingFile + to OverwriteSilently. If you want to cancel the Extraction, set + ZipProgressEventArgs.Cancel to true. Cancelling differs from using + DoNotOverwrite in that a cancel will not extract any further entries, if + there are any. (For COM clients, the value of this enum is a 3.) + + + + + This class exposes a set of COM-accessible wrappers for static + methods available on the ZipFile class. You don't need this + class unless you are using DotNetZip from a COM environment. + + + + + A wrapper for ZipFile.IsZipFile(string) + + The filename to of the zip file to check. + true if the file contains a valid zip file. + + + + A wrapper for ZipFile.IsZipFile(string, bool) + + + We cannot use "overloaded" Method names in COM interop. + So, here, we use a unique name. + + The filename to of the zip file to check. + true if the file contains a valid zip file. + + + + A wrapper for ZipFile.CheckZip(string) + + The filename to of the zip file to check. + + true if the named zip file checks OK. Otherwise, false. + + + + A COM-friendly wrapper for the static method . + + + The filename to of the zip file to check. + + The password to check. + + true if the named zip file checks OK. Otherwise, false. + + + + A wrapper for ZipFile.FixZipDirectory(string) + + The filename to of the zip file to fix. + + + + A wrapper for ZipFile.LibraryVersion + + + the version number on the DotNetZip assembly, formatted as a string. + + + + + Sort-of like a factory method, ForUpdate is used only when + the application needs to update the zip entry metadata for + a segmented zip file, when the starting segment is earlier + than the ending segment, for a particular entry. + + + + The update is always contiguous, never rolls over. As a + result, this method doesn't need to return a ZSS; it can + simply return a FileStream. That's why it's "sort of" + like a Factory method. + + + Caller must Close/Dispose the stream object returned by + this method. + + + + + + Read from the stream + + the buffer to read + the offset at which to start + the number of bytes to read + the number of bytes actually read + + + + Write to the stream. + + the buffer from which to write + the offset at which to start writing + the number of bytes to write + + + + Name of the filesystem file corresponding to the current segment. + + + + The name is not always the name currently being used in the + filesystem. When rwMode is RwMode.Write, the filesystem file has a + temporary name until the stream is closed or until the next segment is + started. + + + + + + Map from a distance to a distance code. + + + No side effects. _dist_code[256] and _dist_code[257] are never used. + + + + + A class for compressing and decompressing streams using the Deflate algorithm. + + + + + + The DeflateStream is a Decorator on a . It adds DEFLATE compression or decompression to any + stream. + + + + Using this stream, applications can compress or decompress data via stream + Read and Write operations. Either compresssion or decompression + can occur through either reading or writing. The compression format used is + DEFLATE, which is documented in IETF RFC 1951, "DEFLATE + Compressed Data Format Specification version 1.3.". + + + + This class is similar to , except that + ZlibStream adds the RFC + 1950 - ZLIB framing bytes to a compressed stream when compressing, or + expects the RFC1950 framing bytes when decompressing. The DeflateStream + does not. + + + + + + + + + + Create a DeflateStream using the specified CompressionMode. + + + + When mode is CompressionMode.Compress, the DeflateStream will use + the default compression level. The "captive" stream will be closed when + the DeflateStream is closed. + + + + This example uses a DeflateStream to compress data from a file, and writes + the compressed data to another file. + + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(fileToCompress + ".deflated")) + { + using (Stream compressor = new DeflateStream(raw, CompressionMode.Compress)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n; + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(fileToCompress & ".deflated") + Using compressor As Stream = New DeflateStream(raw, CompressionMode.Compress) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + The stream which will be read or written. + Indicates whether the DeflateStream will compress or decompress. + + + + Create a DeflateStream using the specified CompressionMode and the specified CompressionLevel. + + + + + + When mode is CompressionMode.Decompress, the level parameter is + ignored. The "captive" stream will be closed when the DeflateStream is + closed. + + + + + + + This example uses a DeflateStream to compress data from a file, and writes + the compressed data to another file. + + + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(fileToCompress + ".deflated")) + { + using (Stream compressor = new DeflateStream(raw, + CompressionMode.Compress, + CompressionLevel.BestCompression)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n= -1; + while (n != 0) + { + if (n > 0) + compressor.Write(buffer, 0, n); + n= input.Read(buffer, 0, buffer.Length); + } + } + } + } + + + + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(fileToCompress & ".deflated") + Using compressor As Stream = New DeflateStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + The stream to be read or written while deflating or inflating. + Indicates whether the DeflateStream will compress or decompress. + A tuning knob to trade speed for effectiveness. + + + + Create a DeflateStream using the specified + CompressionMode, and explicitly specify whether the + stream should be left open after Deflation or Inflation. + + + + + + This constructor allows the application to request that the captive stream + remain open after the deflation or inflation occurs. By default, after + Close() is called on the stream, the captive stream is also + closed. In some cases this is not desired, for example if the stream is a + memory stream that will be re-read after compression. Specify true for + the parameter to leave the stream open. + + + + The DeflateStream will use the default compression level. + + + + See the other overloads of this constructor for example code. + + + + + The stream which will be read or written. This is called the + "captive" stream in other places in this documentation. + + + + Indicates whether the DeflateStream will compress or decompress. + + + true if the application would like the stream to + remain open after inflation/deflation. + + + + Create a DeflateStream using the specified CompressionMode + and the specified CompressionLevel, and explicitly specify whether + the stream should be left open after Deflation or Inflation. + + + + + + When mode is CompressionMode.Decompress, the level parameter is ignored. + + + + This constructor allows the application to request that the captive stream + remain open after the deflation or inflation occurs. By default, after + Close() is called on the stream, the captive stream is also + closed. In some cases this is not desired, for example if the stream is a + that will be re-read after + compression. Specify true for the parameter + to leave the stream open. + + + + + + + This example shows how to use a DeflateStream to compress data from + a file, and store the compressed data into another file. + + + using (var output = System.IO.File.Create(fileToCompress + ".deflated")) + { + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (Stream compressor = new DeflateStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, true)) + { + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n= -1; + while (n != 0) + { + if (n > 0) + compressor.Write(buffer, 0, n); + n= input.Read(buffer, 0, buffer.Length); + } + } + } + // can write additional data to the output stream here + } + + + + Using output As FileStream = File.Create(fileToCompress & ".deflated") + Using input As Stream = File.OpenRead(fileToCompress) + Using compressor As Stream = New DeflateStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, True) + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + ' can write additional data to the output stream here. + End Using + + + The stream which will be read or written. + Indicates whether the DeflateStream will compress or decompress. + true if the application would like the stream to remain open after inflation/deflation. + A tuning knob to trade speed for effectiveness. + + + + Dispose the stream. + + + + This may or may not result in a Close() call on the captive + stream. See the constructors that have a leaveOpen parameter + for more information. + + + Application code won't call this code directly. This method may be + invoked in two distinct scenarios. If disposing == true, the method + has been called directly or indirectly by a user's code, for example + via the public Dispose() method. In this case, both managed and + unmanaged resources can be referenced and disposed. If disposing == + false, the method has been called by the runtime from inside the + object finalizer and this method should not reference other objects; + in that case only unmanaged resources must be referenced or + disposed. + + + + true if the Dispose method was invoked by user code. + + + + + Flush the stream. + + + + + Read data from the stream. + + + + + If you wish to use the DeflateStream to compress data while + reading, you can create a DeflateStream with + CompressionMode.Compress, providing an uncompressed data stream. + Then call Read() on that DeflateStream, and the data read will be + compressed as you read. If you wish to use the DeflateStream to + decompress data while reading, you can create a DeflateStream with + CompressionMode.Decompress, providing a readable compressed data + stream. Then call Read() on that DeflateStream, and the data read + will be decompressed as you read. + + + + A DeflateStream can be used for Read() or Write(), but not both. + + + + The buffer into which the read data should be placed. + the offset within that data array to put the first byte read. + the number of bytes to read. + the number of bytes actually read + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Write data to the stream. + + + + + If you wish to use the DeflateStream to compress data while + writing, you can create a DeflateStream with + CompressionMode.Compress, and a writable output stream. Then call + Write() on that DeflateStream, providing uncompressed data + as input. The data sent to the output stream will be the compressed form + of the data written. If you wish to use the DeflateStream to + decompress data while writing, you can create a DeflateStream with + CompressionMode.Decompress, and a writable output stream. Then + call Write() on that stream, providing previously compressed + data. The data sent to the output stream will be the decompressed form of + the data written. + + + + A DeflateStream can be used for Read() or Write(), + but not both. + + + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Compress a string into a byte array using DEFLATE (RFC 1951). + + + + Uncompress it with . + + + DeflateStream.UncompressString(byte[]) + DeflateStream.CompressBuffer(byte[]) + GZipStream.CompressString(string) + ZlibStream.CompressString(string) + + + A string to compress. The string will first be encoded + using UTF8, then compressed. + + + The string in compressed form + + + + Compress a byte array into a new byte array using DEFLATE. + + + + Uncompress it with . + + + DeflateStream.CompressString(string) + DeflateStream.UncompressBuffer(byte[]) + GZipStream.CompressBuffer(byte[]) + ZlibStream.CompressBuffer(byte[]) + + + A buffer to compress. + + + The data in compressed form + + + + Uncompress a DEFLATE'd byte array into a single string. + + + DeflateStream.CompressString(String) + DeflateStream.UncompressBuffer(byte[]) + GZipStream.UncompressString(byte[]) + ZlibStream.UncompressString(byte[]) + + + A buffer containing DEFLATE-compressed data. + + + The uncompressed string + + + + Uncompress a DEFLATE'd byte array into a byte array. + + + DeflateStream.CompressBuffer(byte[]) + DeflateStream.UncompressString(byte[]) + GZipStream.UncompressBuffer(byte[]) + ZlibStream.UncompressBuffer(byte[]) + + + A buffer containing data that has been compressed with DEFLATE. + + + The data in uncompressed form + + + + This property sets the flush behavior on the stream. + + See the ZLIB documentation for the meaning of the flush behavior. + + + + + The size of the working buffer for the compression codec. + + + + + The working buffer is used for all stream operations. The default size is + 1024 bytes. The minimum size is 128 bytes. You may get better performance + with a larger buffer. Then again, you might not. You would have to test + it. + + + + Set this before the first call to Read() or Write() on the + stream. If you try to set it afterwards, it will throw. + + + + + + The ZLIB strategy to be used during compression. + + + + By tweaking this parameter, you may be able to optimize the compression for + data with particular characteristics. + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the total bytes + written out, if used in writing, or the total bytes read in, if used in + reading. The count may refer to compressed bytes or uncompressed bytes, + depending on how you've used the stream. + + + + + Options for using ZIP64 extensions when saving zip archives. + + + + + + Designed many years ago, the original zip + specification from PKWARE allowed for 32-bit quantities for the + compressed and uncompressed sizes of zip entries, as well as a 32-bit quantity + for specifying the length of the zip archive itself, and a maximum of 65535 + entries. These limits are now regularly exceeded in many backup and archival + scenarios. Recently, PKWare added extensions to the original zip spec, called + "ZIP64 extensions", to raise those limitations. This property governs whether + DotNetZip will use those extensions when writing zip archives. The use of + these extensions is optional and explicit in DotNetZip because, despite the + status of ZIP64 as a bona fide standard, many other zip tools and libraries do + not support ZIP64, and therefore a zip file with ZIP64 extensions may be + unreadable by some of those other tools. + + + + Set this property to to always use ZIP64 + extensions when saving, regardless of whether your zip archive needs it. + Suppose you add 5 files, each under 100k, to a ZipFile. If you specify Always + for this flag, you will get a ZIP64 archive, though the archive does not need + to use ZIP64 because none of the original zip limits had been exceeded. + + + + Set this property to to tell the DotNetZip + library to never use ZIP64 extensions. This is useful for maximum + compatibility and interoperability, at the expense of the capability of + handling large files or large archives. NB: Windows Explorer in Windows XP + and Windows Vista cannot currently extract files from a zip64 archive, so if + you want to guarantee that a zip archive produced by this library will work in + Windows Explorer, use Never. If you set this property to , and your application creates a zip that would + exceed one of the Zip limits, the library will throw an exception while saving + the zip file. + + + + Set this property to to tell the + DotNetZip library to use the ZIP64 extensions when required by the + entry. After the file is compressed, the original and compressed sizes are + checked, and if they exceed the limits described above, then zip64 can be + used. That is the general idea, but there is an additional wrinkle when saving + to a non-seekable device, like the ASP.NET Response.OutputStream, or + Console.Out. When using non-seekable streams for output, the entry + header - which indicates whether zip64 is in use - is emitted before it is + known if zip64 is necessary. It is only after all entries have been saved + that it can be known if ZIP64 will be required. On seekable output streams, + after saving all entries, the library can seek backward and re-emit the zip + file header to be consistent with the actual ZIP64 requirement. But using a + non-seekable output stream, the library cannot seek backward, so the header + can never be changed. In other words, the archive's use of ZIP64 extensions is + not alterable after the header is emitted. Therefore, when saving to + non-seekable streams, using is the same + as using : it will always produce a zip + archive that uses ZIP64 extensions. + + + + + + + The default behavior, which is "Never". + (For COM clients, this is a 0 (zero).) + + + + + Do not use ZIP64 extensions when writing zip archives. + (For COM clients, this is a 0 (zero).) + + + + + Use ZIP64 extensions when writing zip archives, as necessary. + For example, when a single entry exceeds 0xFFFFFFFF in size, or when the archive as a whole + exceeds 0xFFFFFFFF in size, or when there are more than 65535 entries in an archive. + (For COM clients, this is a 1.) + + + + + Always use ZIP64 extensions when writing zip archives, even when unnecessary. + (For COM clients, this is a 2.) + + + + + An enum representing the values on a three-way toggle switch + for various options in the library. This might be used to + specify whether to employ a particular text encoding, or to use + ZIP64 extensions, or some other option. + + + + + The default behavior. This is the same as "Never". + (For COM clients, this is a 0 (zero).) + + + + + Never use the associated option. + (For COM clients, this is a 0 (zero).) + + + + + Use the associated behavior "as necessary." + (For COM clients, this is a 1.) + + + + + Use the associated behavior Always, whether necessary or not. + (For COM clients, this is a 2.) + + + + + Issued when an ZipEntry.ExtractWithPassword() method is invoked + with an incorrect password. + + + + + Base class for all exceptions defined by and throw by the Zip library. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Indicates that a read was attempted on a stream, and bad or incomplete data was + received. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Issued when an CRC check fails upon extracting an entry from a zip archive. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Issued when errors occur saving a self-extracting archive. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Indicates that an operation was attempted on a ZipFile which was not possible + given the state of the instance. For example, if you call Save() on a ZipFile + which has no filename set, you can get this exception. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Describes how to flush the current deflate operation. + + + The different FlushType values are useful when using a Deflate in a streaming application. + + + + No flush at all. + + + Closes the current block, but doesn't flush it to + the output. Used internally only in hypothetical + scenarios. This was supposed to be removed by Zlib, but it is + still in use in some edge cases. + + + + + Use this during compression to specify that all pending output should be + flushed to the output buffer and the output should be aligned on a byte + boundary. You might use this in a streaming communication scenario, so that + the decompressor can get all input data available so far. When using this + with a ZlibCodec, AvailableBytesIn will be zero after the call if + enough output space has been provided before the call. Flushing will + degrade compression and so it should be used only when necessary. + + + + + Use this during compression to specify that all output should be flushed, as + with FlushType.Sync, but also, the compression state should be reset + so that decompression can restart from this point if previous compressed + data has been damaged or if random access is desired. Using + FlushType.Full too often can significantly degrade the compression. + + + + Signals the end of the compression/decompression stream. + + + + The compression level to be used when using a DeflateStream or ZlibStream with CompressionMode.Compress. + + + + + None means that the data will be simply stored, with no change at all. + If you are producing ZIPs for use on Mac OSX, be aware that archives produced with CompressionLevel.None + cannot be opened with the default zip reader. Use a different CompressionLevel. + + + + + Same as None. + + + + + The fastest but least effective compression. + + + + + A synonym for BestSpeed. + + + + + A little slower, but better, than level 1. + + + + + A little slower, but better, than level 2. + + + + + A little slower, but better, than level 3. + + + + + A little slower than level 4, but with better compression. + + + + + The default compression level, with a good balance of speed and compression efficiency. + + + + + A synonym for Default. + + + + + Pretty good compression! + + + + + Better compression than Level7! + + + + + The "best" compression, where best means greatest reduction in size of the input data stream. + This is also the slowest compression. + + + + + A synonym for BestCompression. + + + + + Describes options for how the compression algorithm is executed. Different 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. + + + + + The default strategy is probably the best for normal data. + + + + + The Filtered strategy is intended to be used most effectively with data produced by a + filter or predictor. By this definition, filtered data consists mostly of small + values with a somewhat random distribution. In this case, the compression algorithm + is tuned to compress them better. The effect of Filtered is to force more Huffman + coding and less string matching; it is a half-step between Default and HuffmanOnly. + + + + + Using HuffmanOnly will force the compressor to do Huffman encoding only, with no + string matching. + + + + + An enum to specify the direction of transcoding - whether to compress or decompress. + + + + + Used to specify that the stream should compress the data. + + + + + Used to specify that the stream should decompress the data. + + + + + A general purpose exception class for exceptions in the Zlib library. + + + + + The ZlibException class captures exception information generated + by the Zlib library. + + + + + This ctor collects a message attached to the exception. + + the message for the exception. + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + + Reads a number of characters from the current source TextReader and writes + the data to the target array at the specified index. + + + The source TextReader to read from + Contains the array of characteres read from the source TextReader. + The starting index of the target array. + The maximum number of characters to read from the source TextReader. + + + The number of characters read. The number will be less than or equal to + count depending on the data available in the source TextReader. Returns -1 + if the end of the stream is reached. + + + + + Computes an Adler-32 checksum. + + + The Adler checksum is similar to a CRC checksum, but faster to compute, though less + reliable. It is used in producing RFC1950 compressed streams. The Adler checksum + is a required part of the "ZLIB" standard. Applications will almost never need to + use this class directly. + + + + + + + Calculates the Adler32 checksum. + + + + This is used within ZLIB. You probably don't need to use this directly. + + + + To compute an Adler32 checksum on a byte array: + + var adler = Adler.Adler32(0, null, 0, 0); + adler = Adler.Adler32(adler, buffer, index, length); + + + + + + An enum that specifies the source of the ZipEntry. + + + + + Default value. Invalid on a bonafide ZipEntry. + + + + + The entry was instantiated by calling AddFile() or another method that + added an entry from the filesystem. + + + + + The entry was instantiated via or + . + + + + + The ZipEntry was instantiated by reading a zipfile. + + + + + The content for the ZipEntry will be or was provided by the WriteDelegate. + + + + + The content for the ZipEntry will be obtained from the stream dispensed by the OpenDelegate. + The entry was instantiated via . + + + + + The content for the ZipEntry will be or was obtained from a ZipOutputStream. + + + + + Computes a CRC-32. The CRC-32 algorithm is parameterized - you + can set the polynomial and enable or disable bit + reversal. This can be used for GZIP, BZip2, or ZIP. + + + This type is used internally by DotNetZip; it is generally not used + directly by applications wishing to create, read, or manipulate zip + archive files. + + + + + Returns the CRC32 for the specified stream. + + The stream over which to calculate the CRC32 + the CRC32 calculation + + + + Returns the CRC32 for the specified stream, and writes the input into the + output stream. + + The stream over which to calculate the CRC32 + The stream into which to deflate the input + the CRC32 calculation + + + + Get the CRC32 for the given (word,byte) combo. This is a + computation defined by PKzip for PKZIP 2.0 (weak) encryption. + + The word to start with. + The byte to combine it with. + The CRC-ized result. + + + + Update the value for the running CRC32 using the given block of bytes. + This is useful when using the CRC32() class in a Stream. + + block of bytes to slurp + starting point in the block + how many bytes within the block to slurp + + + + Process one byte in the CRC. + + the byte to include into the CRC . + + + + Process a run of N identical bytes into the CRC. + + + + This method serves as an optimization for updating the CRC when a + run of identical bytes is found. Rather than passing in a buffer of + length n, containing all identical bytes b, this method accepts the + byte value and the length of the (virtual) buffer - the length of + the run. + + + the byte to include into the CRC. + the number of times that byte should be repeated. + + + + Combines the given CRC32 value with the current running total. + + + This is useful when using a divide-and-conquer approach to + calculating a CRC. Multiple threads can each calculate a + CRC32 on a segment of the data, and then combine the + individual CRC32 values at the end. + + the crc value to be combined with this one + the length of data the CRC value was calculated on + + + + Create an instance of the CRC32 class using the default settings: no + bit reversal, and a polynomial of 0xEDB88320. + + + + + Create an instance of the CRC32 class, specifying whether to reverse + data bits or not. + + + specify true if the instance should reverse data bits. + + + + In the CRC-32 used by BZip2, the bits are reversed. Therefore if you + want a CRC32 with compatibility with BZip2, you should pass true + here. In the CRC-32 used by GZIP and PKZIP, the bits are not + reversed; Therefore if you want a CRC32 with compatibility with + those, you should pass false. + + + + + + Create an instance of the CRC32 class, specifying the polynomial and + whether to reverse data bits or not. + + + The polynomial to use for the CRC, expressed in the reversed (LSB) + format: the highest ordered bit in the polynomial value is the + coefficient of the 0th power; the second-highest order bit is the + coefficient of the 1 power, and so on. Expressed this way, the + polynomial for the CRC-32C used in IEEE 802.3, is 0xEDB88320. + + + specify true if the instance should reverse data bits. + + + + + In the CRC-32 used by BZip2, the bits are reversed. Therefore if you + want a CRC32 with compatibility with BZip2, you should pass true + here for the reverseBits parameter. In the CRC-32 used by + GZIP and PKZIP, the bits are not reversed; Therefore if you want a + CRC32 with compatibility with those, you should pass false for the + reverseBits parameter. + + + + + + Reset the CRC-32 class - clear the CRC "remainder register." + + + + Use this when employing a single instance of this class to compute + multiple, distinct CRCs on multiple, distinct data blocks. + + + + + + Indicates the total number of bytes applied to the CRC. + + + + + Indicates the current CRC for all blocks slurped in. + + + + + A Stream that calculates a CRC32 (a checksum) on all bytes read, + or on all bytes written. + + + + + This class can be used to verify the CRC of a ZipEntry when + reading from a stream, or to calculate a CRC when writing to a + stream. The stream should be used to either read, or write, but + not both. If you intermix reads and writes, the results are not + defined. + + + + This class is intended primarily for use internally by the + DotNetZip library. + + + + + + The default constructor. + + + + Instances returned from this constructor will leave the underlying + stream open upon Close(). The stream uses the default CRC32 + algorithm, which implies a polynomial of 0xEDB88320. + + + The underlying stream + + + + The constructor allows the caller to specify how to handle the + underlying stream at close. + + + + The stream uses the default CRC32 algorithm, which implies a + polynomial of 0xEDB88320. + + + The underlying stream + true to leave the underlying stream + open upon close of the CrcCalculatorStream; false otherwise. + + + + A constructor allowing the specification of the length of the stream + to read. + + + + The stream uses the default CRC32 algorithm, which implies a + polynomial of 0xEDB88320. + + + Instances returned from this constructor will leave the underlying + stream open upon Close(). + + + The underlying stream + The length of the stream to slurp + + + + A constructor allowing the specification of the length of the stream + to read, as well as whether to keep the underlying stream open upon + Close(). + + + + The stream uses the default CRC32 algorithm, which implies a + polynomial of 0xEDB88320. + + + The underlying stream + The length of the stream to slurp + true to leave the underlying stream + open upon close of the CrcCalculatorStream; false otherwise. + + + + A constructor allowing the specification of the length of the stream + to read, as well as whether to keep the underlying stream open upon + Close(), and the CRC32 instance to use. + + + + The stream uses the specified CRC32 instance, which allows the + application to specify how the CRC gets calculated. + + + The underlying stream + The length of the stream to slurp + true to leave the underlying stream + open upon close of the CrcCalculatorStream; false otherwise. + the CRC32 instance to use to calculate the CRC32 + + + + Read from the stream + + the buffer to read + the offset at which to start + the number of bytes to read + the number of bytes actually read + + + + Write to the stream. + + the buffer from which to write + the offset at which to start writing + the number of bytes to write + + + + Flush the stream. + + + + + Seeking is not supported on this stream. This method always throws + + + N/A + N/A + N/A + + + + This method always throws + + + N/A + + + + Closes the stream. + + + + + Gets the total number of bytes run through the CRC32 calculator. + + + + This is either the total number of bytes read, or the total number of + bytes written, depending on the direction of this stream. + + + + + Provides the current CRC for all blocks slurped in. + + + + The running total of the CRC is kept as data is written or read + through the stream. read this property after all reads or writes to + get an accurate CRC for the entire stream. + + + + + + Indicates whether the underlying stream will be left open when the + CrcCalculatorStream is Closed. + + + + Set this at any point before calling . + + + + + + Indicates whether the stream supports reading. + + + + + Indicates whether the stream supports seeking. + + + + Always returns false. + + + + + + Indicates whether the stream supports writing. + + + + + Returns the length of the underlying stream. + + + + + The getter for this property returns the total bytes read. + If you use the setter, it will throw + . + + + + + A write-only decorator stream that compresses data as it is + written using the BZip2 algorithm. This stream compresses by + block using multiple threads. + + + This class performs BZIP2 compression through writing. For + more information on the BZIP2 algorithm, see + . + + + + This class is similar to , + except that this implementation uses an approach that employs multiple + worker threads to perform the compression. On a multi-cpu or multi-core + computer, the performance of this class can be significantly higher than + the single-threaded BZip2OutputStream, particularly for larger streams. + How large? Anything over 10mb is a good candidate for parallel + compression. + + + + The tradeoff is that this class uses more memory and more CPU than the + vanilla BZip2OutputStream. Also, for small files, the + ParallelBZip2OutputStream can be much slower than the vanilla + BZip2OutputStream, because of the overhead associated to using the + thread pool. + + + + + + + Constructs a new ParallelBZip2OutputStream, that sends its + compressed output to the given output stream. + + + + The destination stream, to which compressed output will be sent. + + + + + This example reads a file, then compresses it with bzip2 file, + and writes the compressed data into a newly created file. + + + var fname = "logfile.log"; + using (var fs = File.OpenRead(fname)) + { + var outFname = fname + ".bz2"; + using (var output = File.Create(outFname)) + { + using (var compressor = new Ionic.BZip2.ParallelBZip2OutputStream(output)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = fs.Read(buffer, 0, buffer.Length)) > 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + + + Constructs a new ParallelBZip2OutputStream with specified blocksize. + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + + + Constructs a new ParallelBZip2OutputStream. + + the destination stream. + + whether to leave the captive stream open upon closing this stream. + + + + + Constructs a new ParallelBZip2OutputStream with specified blocksize, + and explicitly specifies whether to leave the wrapped stream open. + + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + whether to leave the captive stream open upon closing this stream. + + + + + Close the stream. + + + + This may or may not close the underlying stream. Check the + constructors that accept a bool value. + + + + + + Flush the stream. + + + + + Write data to the stream. + + + + + Use the ParallelBZip2OutputStream to compress data while + writing: create a ParallelBZip2OutputStream with a writable + output stream. Then call Write() on that + ParallelBZip2OutputStream, providing uncompressed data as + input. The data sent to the output stream will be the compressed + form of the input data. + + + + A ParallelBZip2OutputStream can be used only for + Write() not for Read(). + + + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + never returns anything; always throws + + + + The maximum number of concurrent compression worker threads to use. + + + + + This property sets an upper limit on the number of concurrent worker + threads to employ for compression. The implementation of this stream + employs multiple threads from the .NET thread pool, via + ThreadPool.QueueUserWorkItem(), to compress the incoming data by + block. As each block of data is compressed, this stream re-orders the + compressed blocks and writes them to the output stream. + + + + A higher number of workers 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. + + + + By default, DotNetZip allocates 4 workers per CPU core, subject to the + upper limit specified in this property. For example, suppose the + application sets this property to 16. Then, on a machine with 2 + cores, DotNetZip will use 8 workers; that number does not exceed the + upper limit specified by this property, so the actual number of + workers used will be 4 * 2 = 8. On a machine with 4 cores, DotNetZip + will use 16 workers; again, the limit does not apply. On a machine + with 8 cores, DotNetZip will use 16 workers, because of the limit. + + + + For each compression "worker thread" that occurs in parallel, there is + up to 2mb of memory allocated, for buffering and processing. The + actual number depends on the property. + + + + CPU utilization will also go up with additional workers, 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. + + + + The application can set this value at any time, but it is effective + only before the first call to Write(), which is when the buffers are + allocated. + + + + + + The blocksize parameter specified at construction time. + + + + + Indicates whether the stream can be read. + + + The return value is always false. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes written through. + + + + + The total number of bytes written out by the stream. + + + This value is meaningful only after a call to Close(). + + + + + A write-only decorator stream that compresses data as it is + written using the BZip2 algorithm. + + + + + Constructs a new BZip2OutputStream, that sends its + compressed output to the given output stream. + + + + The destination stream, to which compressed output will be sent. + + + + + This example reads a file, then compresses it with bzip2 file, + and writes the compressed data into a newly created file. + + + var fname = "logfile.log"; + using (var fs = File.OpenRead(fname)) + { + var outFname = fname + ".bz2"; + using (var output = File.Create(outFname)) + { + using (var compressor = new Ionic.BZip2.BZip2OutputStream(output)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = fs.Read(buffer, 0, buffer.Length)) > 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + + + Constructs a new BZip2OutputStream with specified blocksize. + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + + + Constructs a new BZip2OutputStream. + + the destination stream. + + whether to leave the captive stream open upon closing this stream. + + + + + Constructs a new BZip2OutputStream with specified blocksize, + and explicitly specifies whether to leave the wrapped stream open. + + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + whether to leave the captive stream open upon closing this stream. + + + + + Close the stream. + + + + This may or may not close the underlying stream. Check the + constructors that accept a bool value. + + + + + + Flush the stream. + + + + + Write data to the stream. + + + + + Use the BZip2OutputStream to compress data while writing: + create a BZip2OutputStream with a writable output stream. + Then call Write() on that BZip2OutputStream, providing + uncompressed data as input. The data sent to the output stream will + be the compressed form of the input data. + + + + A BZip2OutputStream can be used only for Write() not for Read(). + + + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + never returns anything; always throws + + + + The blocksize parameter specified at construction time. + + + + + Indicates whether the stream can be read. + + + The return value is always false. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value should always be true, unless and until the + object is disposed and closed. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes written through. + + + + + An enum that specifies the type of timestamp available on the ZipEntry. + + + + + + The last modified time of a file can be stored in multiple ways in + a zip file, and they are not mutually exclusive: + + + + + In the so-called "DOS" format, which has a 2-second precision. Values + are rounded to the nearest even second. For example, if the time on the + file is 12:34:43, then it will be stored as 12:34:44. This first value + is accessible via the LastModified property. This value is always + present in the metadata for each zip entry. In some cases the value is + invalid, or zero. + + + + In the so-called "Windows" or "NTFS" format, as an 8-byte integer + quantity expressed as the number of 1/10 milliseconds (in other words + the number of 100 nanosecond units) since January 1, 1601 (UTC). This + format is how Windows represents file times. This time is accessible + via the ModifiedTime property. + + + + In the "Unix" format, a 4-byte quantity specifying the number of seconds since + January 1, 1970 UTC. + + + + In an older format, now deprecated but still used by some current + tools. This format is also a 4-byte quantity specifying the number of + seconds since January 1, 1970 UTC. + + + + + + This bit field describes which of the formats were found in a ZipEntry that was read. + + + + + + + Default value. + + + + + A DOS timestamp with 2-second precision. + + + + + A Windows timestamp with 100-ns precision. + + + + + A Unix timestamp with 1-second precision. + + + + + A Unix timestamp with 1-second precision, stored in InfoZip v1 format. This + format is outdated and is supported for reading archives only. + + + + + The method of compression to use for a particular ZipEntry. + + + + PKWare's + ZIP Specification describes a number of distinct + cmopression methods that can be used within a zip + file. DotNetZip supports a subset of them. + + + + + No compression at all. For COM environments, the value is 0 (zero). + + + + + DEFLATE compression, as described in IETF RFC + 1951. This is the "normal" compression used in zip + files. For COM environments, the value is 8. + + + + + BZip2 compression, a compression algorithm developed by Julian Seward. + For COM environments, the value is 12. + + + + + Collects general purpose utility methods. + + + + private null constructor + + + + Utility routine for transforming path names from filesystem format (on Windows that means backslashes) to + a format suitable for use within zipfiles. This means trimming the volume letter and colon (if any) And + swapping backslashes for forward slashes. + + source path. + transformed path + + + + Finds a signature in the zip stream. This is useful for finding + the end of a zip entry, for example, or the beginning of the next ZipEntry. + + + + + Scans through 64k at a time. + + + + If the method fails to find the requested signature, the stream Position + after completion of this method is unchanged. If the method succeeds in + finding the requested signature, the stream position after completion is + direct AFTER the signature found in the stream. + + + + The stream to search + The 4-byte signature to find + The number of bytes read + + + + Create a pseudo-random filename, suitable for use as a temporary + file, and open it. + + + + The System.IO.Path.GetRandomFileName() method is not available on + the Compact Framework, so this library provides its own substitute + on NETCF. + + + This method produces a filename of the form + DotNetZip-xxxxxxxx.tmp, where xxxxxxxx is replaced by randomly + chosen characters, and creates that file. + + + + + + Workitem 7889: handle ERROR_LOCK_VIOLATION during read + + + This could be gracefully handled with an extension attribute, but + This assembly is built for .NET 2.0, so I cannot use them. + + + + + A decorator stream. It wraps another stream, and performs bookkeeping + to keep track of the stream Position. + + + + In some cases, it is not possible to get the Position of a stream, let's + say, on a write-only output stream like ASP.NET's + Response.OutputStream, or on a different write-only stream + provided as the destination for the zip by the application. In this + case, programmers can use this counting stream to count the bytes read + or written. + + + Consider the scenario of an application that saves a self-extracting + archive (SFX), that uses a custom SFX stub. + + + Saving to a filesystem file, the application would open the + filesystem file (getting a FileStream), save the custom sfx stub + into it, and then call ZipFile.Save(), specifying the same + FileStream. ZipFile.Save() does the right thing for the zipentry + offsets, by inquiring the Position of the FileStream before writing + any data, and then adding that initial offset into any ZipEntry + offsets in the zip directory. Everything works fine. + + + Now suppose the application is an ASPNET application and it saves + directly to Response.OutputStream. It's not possible for DotNetZip to + inquire the Position, so the offsets for the SFX will be wrong. + + + The workaround is for the application to use this class to wrap + HttpResponse.OutputStream, then write the SFX stub and the ZipFile + into that wrapper stream. Because ZipFile.Save() can inquire the + Position, it will then do the right thing with the offsets. + + + + + + The constructor. + + The underlying stream + + + + Adjust the byte count on the stream. + + + + the number of bytes to subtract from the count. + + + + + Subtract delta from the count of bytes written to the stream. + This is necessary when seeking back, and writing additional data, + as happens in some cases when saving Zip files. + + + + + + The read method. + + The buffer to hold the data read from the stream. + the offset within the buffer to copy the first byte read. + the number of bytes to read. + the number of bytes read, after decryption and decompression. + + + + Write data into the stream. + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Flushes the underlying stream. + + + + + Seek in the stream. + + the offset point to seek to + the reference point from which to seek + The new position + + + + Set the length of the underlying stream. Be careful with this! + + + the length to set on the underlying stream. + + + + Gets the wrapped stream. + + + + + The count of bytes written out to the stream. + + + + + the count of bytes that have been read from the stream. + + + + + Whether the stream can be read. + + + + + Whether it is possible to call Seek() on the stream. + + + + + Whether it is possible to call Write() on the stream. + + + + + The length of the underlying stream. + + + + + Returns the sum of number of bytes written, plus the initial + offset before writing. + + + + + The Position of the stream. + + + + diff --git a/src/BinaryPatchUtility.cs b/src/BinaryPatchUtility.cs index 1bbd1820..c190821f 100644 --- a/src/BinaryPatchUtility.cs +++ b/src/BinaryPatchUtility.cs @@ -4,7 +4,7 @@ using Ionic.BZip2; // Adapted from https://github.com/LogosBible/bsdiff.net/blob/master/src/bsdiff/BinaryPatchUtility.cs -namespace Squirrel.Core +namespace Squirrel { /* The original bsdiff.c source code (http://www.daemonology.net/bsdiff/) is diff --git a/src/ContentType.cs b/src/ContentType.cs index e1382a78..97fa2c45 100644 --- a/src/ContentType.cs +++ b/src/ContentType.cs @@ -2,7 +2,7 @@ using System; using System.Linq; using System.Xml; -namespace Squirrel.Core +namespace Squirrel { internal static class ContentType { @@ -25,16 +25,21 @@ namespace Squirrel.Core k.GetAttribute("Extension").ToLowerInvariant(), k.GetAttribute("ContentType").ToLowerInvariant())); - elements + var toAdd = elements .Where(x => existingTypes.All(t => t.Item2 != x.Item2.ToLowerInvariant())) .Select(element => { var ret = doc.CreateElement(element.Item1, typesElement.NamespaceURI); + var ext = doc.CreateAttribute("Extension"); ext.Value = element.Item2; var ct = doc.CreateAttribute("ContentType"); ct.Value = element.Item3; - new[] { ext, ct }.ForEach(x => ret.Attributes.Append(x)); + + ret.Attributes.Append(ext); + ret.Attributes.Append(ct); return ret; - }).ForEach(x => typesElement.AppendChild(x)); + }); + + foreach (var v in toAdd) typesElement.AppendChild(v); } } } diff --git a/src/DeltaPackage.cs b/src/DeltaPackage.cs index 36036fd0..a0989a8b 100644 --- a/src/DeltaPackage.cs +++ b/src/DeltaPackage.cs @@ -6,9 +6,9 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using Ionic.Zip; -using ReactiveUIMicro; +using Splat; -namespace Squirrel.Core +namespace Squirrel { public interface IDeltaPackageBuilder { @@ -69,8 +69,9 @@ namespace Squirrel.Core var newLibDir = tempInfo.GetDirectories().First(x => x.Name.ToLowerInvariant() == "lib"); - newLibDir.GetAllFilesRecursively() - .ForEach(libFile => createDeltaForSingleFile(libFile, tempInfo, baseLibFiles)); + foreach (var libFile in newLibDir.GetAllFilesRecursively()) { + createDeltaForSingleFile(libFile, tempInfo, baseLibFiles); + } ReleasePackage.addDeltaFilesToContentTypes(tempInfo.FullName); diff --git a/src/EnumerableExtensions.cs b/src/EnumerableExtensions.cs new file mode 100644 index 00000000..6dc0fea1 --- /dev/null +++ b/src/EnumerableExtensions.cs @@ -0,0 +1,281 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt + +using System.Collections.Generic; + +namespace System.Linq +{ + internal static class EnumerableExtensions + { + /// + /// Enumerates the sequence and invokes the given action for each value in the sequence. + /// + /// Source sequence element type. + /// Source sequence. + /// Action to invoke for each element. + public static void ForEach(this IEnumerable source, Action onNext) + { + if (source == null) + throw new ArgumentNullException("source"); + if (onNext == null) + throw new ArgumentNullException("onNext"); + + foreach (var item in source) onNext(item); + } + + /// + /// Returns the elements with the maximum key value by using the default comparer to compare key values. + /// + /// Source sequence element type. + /// Key type. + /// Source sequence. + /// Key selector used to extract the key for each element in the sequence. + /// List with the elements that share the same maximum key value. + public static IList MaxBy(this IEnumerable source, Func keySelector) + { + if (source == null) + throw new ArgumentNullException("source"); + if (keySelector == null) + throw new ArgumentNullException("keySelector"); + + return MaxBy(source, keySelector, Comparer.Default); + } + + /// + /// Returns the elements with the minimum key value by using the specified comparer to compare key values. + /// + /// Source sequence element type. + /// Key type. + /// Source sequence. + /// Key selector used to extract the key for each element in the sequence. + /// Comparer used to determine the maximum key value. + /// List with the elements that share the same maximum key value. + public static IList MaxBy(this IEnumerable source, Func keySelector, IComparer comparer) + { + if (source == null) + throw new ArgumentNullException("source"); + if (keySelector == null) + throw new ArgumentNullException("keySelector"); + if (comparer == null) + throw new ArgumentNullException("comparer"); + + return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue)); + } + + private static IList ExtremaBy(IEnumerable source, Func keySelector, Func compare) + { + var result = new List(); + + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + throw new InvalidOperationException("Source sequence doesn't contain any elements."); + + var current = e.Current; + var resKey = keySelector(current); + result.Add(current); + + while (e.MoveNext()) + { + var cur = e.Current; + var key = keySelector(cur); + + var cmp = compare(key, resKey); + if (cmp == 0) + { + result.Add(cur); + } + else if (cmp > 0) + { + result = new List { cur }; + resKey = key; + } + } + } + + return result; + } + + /// + /// Lazily invokes an action for each value in the sequence. + /// + /// Source sequence element type. + /// Source sequence. + /// Action to invoke for each element. + /// Sequence exhibiting the specified side-effects upon enumeration. + public static IEnumerable Do(this IEnumerable source, Action onNext) + { + if (source == null) + throw new ArgumentNullException("source"); + if (onNext == null) + throw new ArgumentNullException("onNext"); + + return DoHelper(source, onNext, _ => { }, () => { }); + } + + /// + /// Lazily invokes an action for each value in the sequence, and executes an action for successful termination. + /// + /// Source sequence element type. + /// Source sequence. + /// Action to invoke for each element. + /// Action to invoke on successful termination of the sequence. + /// Sequence exhibiting the specified side-effects upon enumeration. + public static IEnumerable Do(this IEnumerable source, Action onNext, Action onCompleted) + { + if (source == null) + throw new ArgumentNullException("source"); + if (onNext == null) + throw new ArgumentNullException("onNext"); + if (onCompleted == null) + throw new ArgumentNullException("onCompleted"); + + return DoHelper(source, onNext, _ => { }, onCompleted); + } + + /// + /// Lazily invokes an action for each value in the sequence, and executes an action upon exceptional termination. + /// + /// Source sequence element type. + /// Source sequence. + /// Action to invoke for each element. + /// Action to invoke on exceptional termination of the sequence. + /// Sequence exhibiting the specified side-effects upon enumeration. + public static IEnumerable Do(this IEnumerable source, Action onNext, Action onError) + { + if (source == null) + throw new ArgumentNullException("source"); + if (onNext == null) + throw new ArgumentNullException("onNext"); + if (onError == null) + throw new ArgumentNullException("onError"); + + return DoHelper(source, onNext, onError, () => { }); + } + + /// + /// Lazily invokes an action for each value in the sequence, and executes an action upon successful or exceptional termination. + /// + /// Source sequence element type. + /// Source sequence. + /// Action to invoke for each element. + /// Action to invoke on exceptional termination of the sequence. + /// Action to invoke on successful termination of the sequence. + /// Sequence exhibiting the specified side-effects upon enumeration. + public static IEnumerable Do(this IEnumerable source, Action onNext, Action onError, Action onCompleted) + { + if (source == null) + throw new ArgumentNullException("source"); + if (onNext == null) + throw new ArgumentNullException("onNext"); + if (onError == null) + throw new ArgumentNullException("onError"); + if (onCompleted == null) + throw new ArgumentNullException("onCompleted"); + + return DoHelper(source, onNext, onError, onCompleted); + } + + private static IEnumerable DoHelper(this IEnumerable source, Action onNext, Action onError, Action onCompleted) + { + using (var e = source.GetEnumerator()) + { + while (true) + { + var current = default(TSource); + try + { + if (!e.MoveNext()) + break; + + current = e.Current; + } + catch (Exception ex) + { + onError(ex); + throw; + } + + onNext(current); + yield return current; + } + + onCompleted(); + } + } + + /// + /// Returns the source sequence prefixed with the specified value. + /// + /// Source sequence element type. + /// Source sequence. + /// Values to prefix the sequence with. + /// Sequence starting with the specified prefix value, followed by the source sequence. + public static IEnumerable StartWith(this IEnumerable source, params TSource[] values) + { + if (source == null) + throw new ArgumentNullException("source"); + + return source.StartWith_(values); + } + + static IEnumerable StartWith_(this IEnumerable source, params TSource[] values) + { + foreach (var x in values) + yield return x; + + foreach (var item in source) + yield return item; + } + + /// + /// Returns elements with a distinct key value by using the default equality comparer to compare key values. + /// + /// Source sequence element type. + /// Key type. + /// Source sequence. + /// Key selector. + /// Sequence that contains the elements from the source sequence with distinct key values. + public static IEnumerable Distinct(this IEnumerable source, Func keySelector) + { + if (source == null) + throw new ArgumentNullException("source"); + if (keySelector == null) + throw new ArgumentNullException("keySelector"); + + return source.Distinct_(keySelector, EqualityComparer.Default); + } + + /// + /// Returns elements with a distinct key value by using the specified equality comparer to compare key values. + /// + /// Source sequence element type. + /// Key type. + /// Source sequence. + /// Key selector. + /// Comparer used to compare key values. + /// Sequence that contains the elements from the source sequence with distinct key values. + public static IEnumerable Distinct(this IEnumerable source, Func keySelector, IEqualityComparer comparer) + { + if (source == null) + throw new ArgumentNullException("source"); + if (keySelector == null) + throw new ArgumentNullException("keySelector"); + if (comparer == null) + throw new ArgumentNullException("comparer"); + + return source.Distinct_(keySelector, comparer); + } + + static IEnumerable Distinct_(this IEnumerable source, Func keySelector, IEqualityComparer comparer) + { + var set = new HashSet(comparer); + + foreach (var item in source) + { + var key = keySelector(item); + if (set.Add(key)) + yield return item; + } + } + } +} diff --git a/src/PackageExtensions.cs b/src/PackageExtensions.cs new file mode 100644 index 00000000..d5c76e55 --- /dev/null +++ b/src/PackageExtensions.cs @@ -0,0 +1,17 @@ +using System; +using NuGet; + +namespace Squirrel +{ + public static class PackageExtensions + { + public static string ExtractTitle(this IPackage package) + { + if (package == null) + return String.Empty; + + var title = package.Title; + return !String.IsNullOrWhiteSpace(title) ? title : package.Id; + } + } +} diff --git a/src/ReleaseEntry.cs b/src/ReleaseEntry.cs index 98879132..ab01370e 100644 --- a/src/ReleaseEntry.cs +++ b/src/ReleaseEntry.cs @@ -3,15 +3,15 @@ using System.Collections.Generic; using System.Diagnostics.Contracts; using System.IO; using System.Linq; -using System.Reactive.Linq; using System.Text; using System.Text.RegularExpressions; using NuGet; -using ReactiveUIMicro; -using Squirrel.Core.Extensions; +using Splat; using System.Runtime.Serialization; +using System.Threading.Tasks; +using System.Collections.Concurrent; -namespace Squirrel.Core +namespace Squirrel { public interface IReleaseEntry { @@ -150,25 +150,24 @@ namespace Squirrel.Core } } - public static void BuildReleasesFile(string releasePackagesDir, IFileSystemFactory fileSystemFactory = null) + public static void BuildReleasesFile(string releasePackagesDir) { - fileSystemFactory = fileSystemFactory ?? AnonFileSystem.Default; - var packagesDir = fileSystemFactory.GetDirectoryInfo(releasePackagesDir); + var packagesDir = new DirectoryInfo(releasePackagesDir); // Generate release entries for all of the local packages - var entries = packagesDir.GetFiles("*.nupkg").MapReduce(x => Observable.Start(() => { + var entriesQueue = new ConcurrentQueue(); + Parallel.ForEach(packagesDir.GetFiles("*.nupkg"), x => { using (var file = x.OpenRead()) { - return GenerateFromFile(file, x.Name); + entriesQueue.Enqueue(GenerateFromFile(file, x.Name)); } - }, RxApp.TaskpoolScheduler)).First(); + }); // Write the new RELEASES file to a temp file then move it into // place - var tempFile = fileSystemFactory.CreateTempFile(); - try { - if (entries.Count > 0) WriteReleaseFile(entries, tempFile.Item2); - } finally { - tempFile.Item2.Dispose(); + var entries = entriesQueue.ToList(); + var tempFile = Path.GetTempFileName(); + using (var of = File.OpenWrite(tempFile)) { + if (entries.Count > 0) WriteReleaseFile(entries, of); } var target = Path.Combine(packagesDir.FullName, "RELEASES"); @@ -176,7 +175,7 @@ namespace Squirrel.Core File.Delete(target); } - fileSystemFactory.GetFileInfo(tempFile.Item1).MoveTo(target); + File.Move(tempFile, target); } static bool filenameIsDeltaFile(string filename) diff --git a/src/ReleaseExtensions.cs b/src/ReleaseExtensions.cs new file mode 100644 index 00000000..30b431c7 --- /dev/null +++ b/src/ReleaseExtensions.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace Squirrel +{ + public static class VersionExtensions + { + public static Version ToVersion(this IReleasePackage package) + { + return package.InputPackageFile.ToVersion(); + } + + public static Version ToVersion(this string fileName) + { + var parts = (new FileInfo(fileName)).Name + .Replace(".nupkg", "").Replace("-delta", "") + .Split('.', '-').Reverse(); + + var numberRegex = new Regex(@"^\d+$"); + + var versionFields = parts + .Where(x => numberRegex.IsMatch(x)) + .Select(Int32.Parse) + .Reverse() + .ToArray(); + + if (versionFields.Length < 2 || versionFields.Length > 4) + { + return null; + } + + switch (versionFields.Length) + { + case 2: + return new Version(versionFields[0], versionFields[1]); + case 3: + return new Version(versionFields[0], versionFields[1], versionFields[2]); + case 4: + return new Version(versionFields[0], versionFields[1], versionFields[2], versionFields[3]); + } + + return null; + } + } +} diff --git a/src/ReleasePackage.cs b/src/ReleasePackage.cs index 4b36e1c0..735f3eda 100644 --- a/src/ReleasePackage.cs +++ b/src/ReleasePackage.cs @@ -11,10 +11,9 @@ using System.Text.RegularExpressions; using System.Xml; using Ionic.Zip; using NuGet; -using ReactiveUIMicro; -using Squirrel.Core.Extensions; +using Splat; -namespace Squirrel.Core +namespace Squirrel { internal static class FrameworkTargetVersion { diff --git a/src/Utility.cs b/src/Utility.cs index a9e6cb26..b50b04ee 100644 --- a/src/Utility.cs +++ b/src/Utility.cs @@ -4,21 +4,18 @@ using System.ComponentModel; using System.Diagnostics.Contracts; using System.IO; using System.Linq; -using System.Reactive; -using System.Reactive.Concurrency; -using System.Reactive.Disposables; -using System.Reactive.Linq; -using System.Reactive.Subjects; using System.Reflection; using System.Runtime.InteropServices; using System.Security.AccessControl; using System.Security.Cryptography; using System.Security.Principal; using System.Threading; -using ReactiveUIMicro; +using Splat; using System.Text; +using System.Threading.Tasks; +using System.Collections.Concurrent; -namespace Squirrel.Core +namespace Squirrel { public static class Utility { @@ -58,7 +55,7 @@ namespace Squirrel.Core } } - public static IObservable CopyToAsync(string from, string to) + public static async Task CopyToAsync(string from, string to) { Contract.Requires(!String.IsNullOrEmpty(from) && File.Exists(from)); Contract.Requires(!String.IsNullOrEmpty(to)); @@ -67,11 +64,11 @@ namespace Squirrel.Core Log().Warn("The file {0} does not exist", from); // TODO: should we fail this operation? - return Observable.Return(Unit.Default); + return; } // XXX: SafeCopy - return Observable.Start(() => File.Copy(from, to, true), RxApp.TaskpoolScheduler); + await Task.Run(() => File.Copy(from, to, true)); } public static void Retry(this Action block, int retries = 2) @@ -105,14 +102,20 @@ namespace Squirrel.Core } } - public static IObservable> MapReduce(this IObservable This, Func> selector, int degreeOfParallelism = 4) + public static Task ForEachAsync(this IEnumerable source, Action body, int degreeOfParallelism = 4) { - return This.Select(x => Observable.Defer(() => selector(x))).Merge(degreeOfParallelism).ToList(); + return ForEachAsync(source, x => Task.Run(() => body(x)), degreeOfParallelism); } - public static IObservable> MapReduce(this IEnumerable This, Func> selector, int degreeOfParallelism = 4) + public static Task ForEachAsync(this IEnumerable source, Func body, int degreeOfParallelism = 4) { - return This.ToObservable().Select(x => Observable.Defer(() => selector(x))).Merge(degreeOfParallelism).ToList(); + return Task.WhenAll( + from partition in Partitioner.Create(source).GetPartitions(degreeOfParallelism) + select Task.Run(async () => { + using (partition) + while (partition.MoveNext()) + await body(partition.Current); + })); } static string directoryChars; @@ -147,17 +150,15 @@ namespace Squirrel.Core DeleteDirectory(tempDir.FullName).Wait()); } - public static IObservable DeleteDirectory(string directoryPath, IScheduler scheduler = null) + public static async Task DeleteDirectory(string directoryPath) { Contract.Requires(!String.IsNullOrEmpty(directoryPath)); - scheduler = scheduler ?? RxApp.TaskpoolScheduler; - Log().Info("Starting to delete folder: {0}", directoryPath); if (!Directory.Exists(directoryPath)) { Log().Warn("DeleteDirectory: does not exist - {0}", directoryPath); - return Observable.Return(Unit.Default); + return; } // From http://stackoverflow.com/questions/329355/cannot-delete-directory-with-directory-deletepath-true/329502#329502 @@ -177,34 +178,25 @@ namespace Squirrel.Core Log().Warn(message, ex); } - var fileOperations = files.MapReduce(file => - Observable.Start(() => { - Log().Debug("Now deleting file: {0}", file); - File.SetAttributes(file, FileAttributes.Normal); - File.Delete(file); - }, scheduler)) - .Select(_ => Unit.Default); + var fileOperations = files.ForEachAsync(file => { + File.SetAttributes(file, FileAttributes.Normal); + File.Delete(file); + }); var directoryOperations = - dirs.MapReduce(dir => DeleteDirectory(dir, scheduler) - .Retry(3)) - .Select(_ => Unit.Default); + dirs.ForEachAsync(async dir => await DeleteDirectory(dir)); - return fileOperations - .Merge(directoryOperations, scheduler) - .ToList() // still feeling a bit icky - .Select(_ => { - Log().Debug("Now deleting folder: {0}", directoryPath); - File.SetAttributes(directoryPath, FileAttributes.Normal); + await Task.WhenAll(fileOperations, directoryOperations); - try { - Directory.Delete(directoryPath, false); - } catch (Exception ex) { - var message = String.Format("DeleteDirectory: could not delete - {0}", directoryPath); - Log().ErrorException(message, ex); - } - return Unit.Default; - }); + Log().Debug("Now deleting folder: {0}", directoryPath); + File.SetAttributes(directoryPath, FileAttributes.Normal); + + try { + Directory.Delete(directoryPath, false); + } catch (Exception ex) { + var message = String.Format("DeleteDirectory: could not delete - {0}", directoryPath); + Log().ErrorException(message, ex); + } } public static Tuple CreateTempFile() @@ -251,9 +243,11 @@ namespace Squirrel.Core Log().Error("safeDeleteFileAtNextReboot: failed - {0} - {1}", name, lastError); } - static IRxUIFullLogger Log() + static IFullLogger logger; + static IFullLogger Log() { - return LogManager.GetLogger(typeof(Utility)); + return logger ?? + (logger = Locator.CurrentMutable.GetService().GetLogger(typeof(Utility))); } [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] @@ -271,6 +265,7 @@ namespace Squirrel.Core } } + /* public sealed class SingleGlobalInstance : IDisposable { readonly static object gate = 42; @@ -331,4 +326,29 @@ namespace Squirrel.Core lockScheduler.Dispose(); } } + */ + + public static class Disposable + { + public static IDisposable Create(Action action) + { + return new AnonDisposable(action); + } + + class AnonDisposable : IDisposable + { + static readonly Action dummyBlock = (() => { }); + Action block; + + public AnonDisposable(Action b) + { + block = b; + } + + public void Dispose() + { + Interlocked.Exchange(ref block, dummyBlock)(); + } + } + } } diff --git a/src/packages.config b/src/packages.config index 61672b2d..7fcdc7d0 100644 --- a/src/packages.config +++ b/src/packages.config @@ -2,4 +2,5 @@ + \ No newline at end of file