/// <summary> /// Read the next entry from the zip file. /// </summary> /// /// <remarks> /// <para> /// Call this method just before calling <see cref="Read(byte[], int, int)"/>, /// to position the pointer in the zip file to the next entry that can be /// read. Subsequent calls to <c>Read()</c>, will decrypt and decompress the /// data in the zip file, until <c>Read()</c> returns 0. /// </para> /// /// <para> /// Each time you call <c>GetNextEntry()</c>, the pointer in the wrapped /// stream is moved to the next entry in the zip file. If you call <see /// cref="Seek(long, SeekOrigin)"/>, and thus re-position the pointer within /// the file, you will need to call <c>GetNextEntry()</c> again, to insure /// that the file pointer is positioned at the beginning of a zip entry. /// </para> /// /// <para> /// This method returns the <c>ZipEntry</c>. Using a stream approach, you will /// read the raw bytes for an entry in a zip file via calls to <c>Read()</c>. /// Alternatively, you can extract an entry into a file, or a stream, by /// calling <see cref="ZipEntry.Extract()"/>, or one of its siblings. /// </para> /// /// </remarks> /// /// <returns> /// The <c>ZipEntry</c> read. Returns null (or Nothing in VB) if there are no more /// entries in the zip file. /// </returns> /// public ZipEntry GetNextEntry() { if (_findRequired) { // find the next signature long d = SharedUtilities.FindSignature(_inputStream, ZipConstants.ZipEntrySignature); if (d == -1) { return(null); } // back up 4 bytes: ReadEntry assumes the file pointer is positioned before the entry signature _inputStream.Seek(-4, SeekOrigin.Current); // workitem 10178 SharedUtilities.Workaround_Ladybug318918(_inputStream); } // workitem 10923 else if (_firstEntry) { // we've already read one entry. // Seek to the end of it. _inputStream.Seek(_endOfEntry, SeekOrigin.Begin); SharedUtilities.Workaround_Ladybug318918(_inputStream); } _currentEntry = ZipEntry.ReadEntry(_container, !_firstEntry); // ReadEntry leaves the file position after all the entry // data and the optional bit-3 data descriptpr. This is // where the next entry would normally start. _endOfEntry = _inputStream.Position; _firstEntry = true; _needSetup = true; _findRequired = false; return(_currentEntry); }
/// <summary> /// Read the data from the stream into the buffer. /// </summary> /// /// <remarks> /// <para> /// The data for the zipentry will be decrypted and uncompressed, as /// necessary, before being copied into the buffer. /// </para> /// /// <para> /// You must set the <see cref="Password"/> property before calling /// <c>Read()</c> the first time for an encrypted entry. To determine if an /// entry is encrypted and requires a password, check the <see /// cref="ZipEntry.Encryption">ZipEntry.Encryption</see> property. /// </para> /// </remarks> /// /// <param name="buffer">The buffer to hold the data read from the stream.</param> /// <param name="offset">the offset within the buffer to copy the first byte read.</param> /// <param name="count">the number of bytes to read.</param> /// <returns>the number of bytes read, after decryption and decompression.</returns> public override int Read(byte[] buffer, int offset, int count) { if (_closed) { _exceptionPending = true; throw new System.InvalidOperationException("The stream has been closed."); } if (_needSetup) { SetupStream(); } if (_LeftToRead == 0) { return(0); } int len = (_LeftToRead > count) ? count : (int)_LeftToRead; int n = _crcStream.Read(buffer, offset, len); _LeftToRead -= n; if (_LeftToRead == 0) { int CrcResult = _crcStream.Crc; _currentEntry.VerifyCrcAfterExtract(CrcResult); _inputStream.Seek(_endOfEntry, SeekOrigin.Begin); // workitem 10178 SharedUtilities.Workaround_Ladybug318918(_inputStream); } return(n); }
/// <summary> /// This method seeks in the underlying stream. /// </summary> /// /// <remarks> /// <para> /// Call this method if you want to seek around within the zip file for random access. /// </para> /// /// <para> /// Applications can intermix calls to <c>Seek()</c> with calls to <see /// cref="GetNextEntry()"/>. After a call to <c>Seek()</c>, /// <c>GetNextEntry()</c> will get the next <c>ZipEntry</c> 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. /// </para> /// /// </remarks> /// /// <param name="offset">the offset point to seek to</param> /// <param name="origin">the reference point from which to seek</param> /// <returns>The new position</returns> public override long Seek(long offset, SeekOrigin origin) { _findRequired = true; var x = _inputStream.Seek(offset, origin); // workitem 10178 SharedUtilities.Workaround_Ladybug318918(_inputStream); return(x); }