Class ZipInputStream
Provides a stream metaphor for reading zip files.
public class ZipInputStream : Stream, IAsyncDisposable, IDisposable
- Inheritance
-
ZipInputStream
- Implements
- Inherited Members
- Extension Methods
Remarks
This class provides an alternative programming model for reading zip files to the one enabled by the ZipFile class. Use this when reading zip files, as an alternative to the ZipFile 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.
-
ZipFilecan be used to create or update zip files, or read and extract zip files.ZipInputStreamcan be used only to read and extract zip files. If you want to use a stream to create zip files, check out the ZipOutputStream. -
ZipInputStreamcannot read segmented or spanned zip files. -
ZipInputStreamwill not read Zip file comments. -
When reading larger files,
ZipInputStreamwill always underperformZipFile. This is because theZipInputStreamdoes a full scan on the zip file, while theZipFileclass reads the central directory of the zip file.
Constructors
ZipInputStream(Stream)
Create a ZipInputStream, wrapping it around an existing stream.
public ZipInputStream(Stream stream)
Parameters
streamStreamThe stream to read. It must be readable. This stream will be closed at the time the
ZipInputStreamis closed.
Examples
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
Remarks
While the ZipFile class is generally easier to use, this class provides an alternative to those applications that want to read from a zipfile directly, using a Stream.
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.
-
ZipFilecan be used to create or update zip files, or read and extract zip files.ZipInputStreamcan be used only to read and extract zip files. If you want to use a stream to create zip files, check out the ZipOutputStream. -
ZipInputStreamcannot read segmented or spanned zip files. -
ZipInputStreamwill not read Zip file comments. -
When reading larger files,
ZipInputStreamwill always underperformZipFile. This is because theZipInputStreamdoes a full scan on the zip file, while theZipFileclass reads the central directory of the zip file.
ZipInputStream(Stream, bool)
Create a ZipInputStream, explicitly specifying whether to
keep the underlying stream open.
public ZipInputStream(Stream stream, bool leaveOpen)
Parameters
streamStreamThe stream to read from. It must be readable.
leaveOpenbooltrue if the application would like the stream to remain open after the
ZipInputStreamhas been closed.
Remarks
See the documentation for the ZipInputStream(Stream) constructor for a discussion of the class, and an example of how to use the class.
ZipInputStream(string)
Create a ZipInputStream, given the name of an existing zip file.
public ZipInputStream(string fileName)
Parameters
fileNamestringThe name of the filesystem file to read.
Examples
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
Remarks
This constructor opens a FileStream for the given zipfile, and
wraps a ZipInputStream around that. See the documentation for the
ZipInputStream(Stream) constructor for full details.
While the ZipFile class is generally easier to use, this class provides an alternative to those applications that want to read from a zipfile directly, using a Stream.
Properties
CanRead
Always returns true.
public override bool CanRead { get; }
Property Value
CanSeek
Returns the value of CanSeek for the underlying (wrapped) stream.
public override bool CanSeek { get; }
Property Value
CanWrite
Always returns false.
public override bool CanWrite { get; }
Property Value
CodecBufferSize
Size of the work buffer to use for the ZLIB codec during decompression.
public int CodecBufferSize { get; set; }
Property Value
Remarks
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.
Length
Returns the length of the underlying stream.
public override long Length { get; }
Property Value
Password
Sets the password to be used on the ZipInputStream instance.
public string Password { set; }
Property Value
Examples
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);
}
}
}
}
}
Remarks
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.
Position
Gets or sets the position of the underlying stream.
public override long Position { get; set; }
Property Value
Remarks
Setting the position is equivalent to calling Seek(value, SeekOrigin.Begin).
ProvisionalAlternateEncoding
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.
public Encoding ProvisionalAlternateEncoding { get; set; }
Property Value
Remarks
In its zip specification, PKWare describes two options for encoding filenames and comments: using IBM437 or UTF-8. But, some archiving tools or libraries do not follow the specification, and instead encode characters using the system default code page. For example, WinRAR when run on a machine in Shanghai may encode filenames with the Big-5 Chinese (950) code page. This behavior is contrary to the Zip specification, but it occurs anyway.
When using DotNetZip to 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.
Methods
Dispose(bool)
Dispose the stream.
protected override void Dispose(bool disposing)
Parameters
disposingbooltrue if the Dispose method was invoked by user code.
Remarks
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.
Flush()
This is a no-op.
public override void Flush()
GetNextEntry()
Read the next entry from the zip file.
public ZipEntry GetNextEntry()
Returns
- ZipEntry
The
ZipEntryread. Returns null (or Nothing in VB) if there are no more entries in the zip file.
Remarks
Call this method just before calling Read(byte[], int, int),
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 Seek(long, SeekOrigin), 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 Extract(), or one of its siblings.
Read(byte[], int, int)
Read the data from the stream into the buffer.
public override int Read(byte[] buffer, int offset, int count)
Parameters
bufferbyte[]The buffer to hold the data read from the stream.
offsetintthe offset within the buffer to copy the first byte read.
countintthe number of bytes to read.
Returns
- int
the number of bytes read, after decryption and decompression.
Remarks
The data for the zipentry will be decrypted and uncompressed, as necessary, before being copied into the buffer.
You must set the Password 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.
Seek(long, SeekOrigin)
This method seeks in the underlying stream.
public override long Seek(long offset, SeekOrigin origin)
Parameters
offsetlongthe offset point to seek to
originSeekOriginthe reference point from which to seek
Returns
- long
The new position
Remarks
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 GetNextEntry(). 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.
SetLength(long)
This method always throws a NotSupportedException.
public override void SetLength(long value)
Parameters
valuelongignored
ToString()
Provides a string representation of the instance.
public override string ToString()
Returns
- string
a string representation of the instance.
Remarks
This can be useful for debugging purposes.
Write(byte[], int, int)
This method always throws a NotSupportedException.
public override void Write(byte[] buffer, int offset, int count)