/// <summary> /// Returns a stream for the specified zip file entry. /// </summary> /// <param name="zfe"> /// The zip file entry for which to fetch a stream. /// </param> /// <returns> /// A stream for the specified zip file entry. /// </returns> private Stream GetZipStream(ZipFileEntry zfe) { switch (zfe.Method) { case Compression.Store: return this.zipFileStream; case Compression.Deflate: return new DeflateStream(this.zipFileStream, CompressionMode.Decompress, true); default: return null; } }
/// <summary> /// The matrix cursor. /// </summary> /// <param name="projection"> /// The projection. /// </param> /// <param name="intProjection"> /// The int projection. /// </param> /// <param name="entries"> /// The entries. /// </param> /// <returns> /// The Android.Database.MatrixCursor. /// </returns> private static MatrixCursor MatrixCursor( string[] projection, ApezProjection[] intProjection, ZipFileEntry[] entries) { var mc = new MatrixCursor(projection, entries.Length); foreach (ZipFileEntry zer in entries) { MatrixCursor.RowBuilder rb = mc.NewRow(); for (int i = 0; i < intProjection.Length; i++) { switch (intProjection[i]) { case ApezProjection.File: rb.Add(i); break; case ApezProjection.FileName: rb.Add(zer.FilenameInZip); break; case ApezProjection.ZipFile: rb.Add(zer.ZipFileName); break; case ApezProjection.Modification: rb.Add(ZipFile.DateTimeToDosTime(zer.ModifyTime)); break; case ApezProjection.Crc: rb.Add(zer.Crc32); break; case ApezProjection.CompressedLength: rb.Add(zer.CompressedSize); break; case ApezProjection.UncompressedLength: rb.Add(zer.FileSize); break; case ApezProjection.CompressionType: rb.Add((int)zer.Method); break; } } } return mc; }
/// <summary> /// Loads an entry from the zip file. /// </summary> /// <param name="pointer"> /// The pointer. /// </param> /// <returns> /// An entry at this location /// </returns> private ZipFileEntry GetEntry(ref int pointer) { bool encodeUtf8 = (BitConverter.ToUInt16(this.centralDirImage, pointer + 8) & 0x0800) != 0; ushort method = BitConverter.ToUInt16(this.centralDirImage, pointer + 10); uint modifyTime = BitConverter.ToUInt32(this.centralDirImage, pointer + 12); uint crc32 = BitConverter.ToUInt32(this.centralDirImage, pointer + 16); uint comprSize = BitConverter.ToUInt32(this.centralDirImage, pointer + 20); uint fileSize = BitConverter.ToUInt32(this.centralDirImage, pointer + 24); ushort filenameSize = BitConverter.ToUInt16(this.centralDirImage, pointer + 28); ushort extraSize = BitConverter.ToUInt16(this.centralDirImage, pointer + 30); ushort commentSize = BitConverter.ToUInt16(this.centralDirImage, pointer + 32); uint headerOffset = BitConverter.ToUInt32(this.centralDirImage, pointer + 42); int commentsStart = 46 + filenameSize + extraSize; int headerSize = commentsStart + commentSize; Encoding encoder = encodeUtf8 ? Encoding.UTF8 : Encoding.Default; string comment = null; if (commentSize > 0) { comment = encoder.GetString(this.centralDirImage, pointer + commentsStart, commentSize); } var zfe = new ZipFileEntry { Method = (Compression)method, FilenameInZip = encoder.GetString(this.centralDirImage, pointer + 46, filenameSize), FileOffset = this.GetFileOffset(headerOffset), FileSize = fileSize, CompressedSize = comprSize, HeaderOffset = headerOffset, HeaderSize = (uint)headerSize, Crc32 = crc32, ModifyTime = DosTimeToDateTime(modifyTime), Comment = comment ?? string.Empty, ZipFileName = this.FileName }; pointer += headerSize; return zfe; }
/// <summary> /// Copy the contents of a stored file into an opened stream /// </summary> /// <param name="zfe"> /// Entry information of file to extract /// </param> /// <returns> /// Stream to store the uncompressed data /// </returns> /// <remarks> /// Unique compression methods are Store and Deflate /// </remarks> public Stream ReadFile(ZipFileEntry zfe) { // check signature var signature = new byte[4]; this.zipFileStream.Seek(zfe.HeaderOffset, SeekOrigin.Begin); this.zipFileStream.Read(signature, 0, 4); if (BitConverter.ToUInt32(signature, 0) != 0x04034b50) { throw new InvalidOperationException("Not a valid zip entry."); } // Select input stream for inflating or just reading Stream inStream; switch (zfe.Method) { case Compression.Store: inStream = this.zipFileStream; break; case Compression.Deflate: inStream = new DeflateStream(this.zipFileStream, CompressionMode.Decompress, true); break; default: throw new InvalidOperationException("Not a valid zip entry."); } this.zipFileStream.Seek(zfe.FileOffset, SeekOrigin.Begin); return new ZipStream(inStream, zfe); }
/// <summary> /// Copy the contents of a stored file into an opened stream /// </summary> /// <param name="zfe"> /// Entry information of file to extract /// </param> /// <param name="stream"> /// Stream to store the uncompressed data /// </param> /// <returns> /// True if success, false if not. /// </returns> /// <remarks> /// Unique compression methods are Store and Deflate /// </remarks> public bool ExtractFile(ZipFileEntry zfe, Stream stream) { if (!stream.CanWrite) { throw new InvalidOperationException("Stream cannot be written"); } // check signature var signature = new byte[4]; this.zipFileStream.Seek(zfe.HeaderOffset, SeekOrigin.Begin); this.zipFileStream.Read(signature, 0, 4); if (BitConverter.ToUInt32(signature, 0) != 0x04034b50) { return false; } // Select input stream for inflating or just reading Stream inStream = this.GetZipStream(zfe); if (inStream == null) { return false; } // Buffered copy var buffer = new byte[16384]; this.zipFileStream.Seek(zfe.FileOffset, SeekOrigin.Begin); uint bytesPending = zfe.FileSize; while (bytesPending > 0) { int bytesRead = inStream.Read(buffer, 0, (int)Math.Min(bytesPending, buffer.Length)); stream.Write(buffer, 0, bytesRead); bytesPending -= (uint)bytesRead; } stream.Flush(); if (zfe.Method == Compression.Deflate) { inStream.Dispose(); } return true; }
/// <summary> /// Copy the contents of a stored file into a physical file /// </summary> /// <param name="zfe"> /// Entry information of file to extract /// </param> /// <param name="filename"> /// Name of file to store uncompressed data /// </param> /// <returns> /// True if success, false if not. /// </returns> /// <remarks> /// Unique compression methods are Store and Deflate /// </remarks> public bool ExtractFile(ZipFileEntry zfe, string filename) { // Make sure the parent directory exist string path = Path.GetDirectoryName(filename); if (!string.IsNullOrWhiteSpace(path) && !Directory.Exists(path)) { Directory.CreateDirectory(path); } // Check it is directory. If so, do nothing if (Directory.Exists(filename)) { return true; } Stream output = new FileStream(filename, FileMode.Create, FileAccess.Write); bool result = this.ExtractFile(zfe, output); if (result) { output.Close(); } File.SetCreationTime(filename, zfe.ModifyTime); File.SetLastWriteTime(filename, zfe.ModifyTime); return result; }
/// <summary> /// Copy the contents of a stored file into an opened stream /// </summary> /// <param name="zfe"> /// Entry information of file to extract /// </param> /// <param name="buffer"> /// Stream to store the uncompressed data /// </param> /// <returns> /// True if success, false if not. /// </returns> /// <remarks> /// Unique compression methods are Store and Deflate /// </remarks> public bool ExtractFile(ZipFileEntry zfe, byte[] buffer) { // check signature var signature = new byte[4]; zipFileStream.Seek(zfe.HeaderOffset, SeekOrigin.Begin); zipFileStream.Read(signature, 0, 4); if (BitConverter.ToUInt32(signature, 0) != 0x04034b50) return false; // Select input stream for inflating or just reading Stream inStream = GetZipStream(zfe); if (inStream == null) { return false; } // Buffered copy zipFileStream.Seek(zfe.FileOffset, SeekOrigin.Begin); inStream.Read(buffer, 0, buffer.Length); if (zfe.Method == Compression.Deflate) inStream.Dispose(); return true; }