public override int Read(byte[] buffer, int offset, int count) { if (_streamToCompress == null) { throw new ObjectDisposedException(typeof(ZipOutputStream).Name); } if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "Cannot be negative."); } if (count < 0) { throw new ArgumentOutOfRangeException("count", "Cannot be negative."); } if (offset + count > buffer.Length) { throw new ArgumentException("The sum of offset and count is greater than the byte array length."); } _bufferController = new BufferController(buffer, offset, count); _backlogs = _bufferController.Append(_backlogs).ToList(); while (_bufferController.Availability > 0 && !_eof) { var bytesRead = _streamToCompress.Read(_buffer, 0, _buffer.Length); if (bytesRead == 0) { CompressedStream.CloseEntry(); CompressedStream.Close(); _eof = true; } else { CompressedStream.Write(_buffer, 0, bytesRead); CompressedStream.Flush(); } } return(_bufferController.Count); }
private void WriteHeader(System.IO.Stream s, byte[] bytes) { // write the header info int i = 0; // signature bytes[i++] = (byte)(ZipConstants.ZipEntrySignature & 0x000000FF); bytes[i++] = (byte)((ZipConstants.ZipEntrySignature & 0x0000FF00) >> 8); bytes[i++] = (byte)((ZipConstants.ZipEntrySignature & 0x00FF0000) >> 16); bytes[i++] = (byte)((ZipConstants.ZipEntrySignature & 0xFF000000) >> 24); // version needed Int16 FixedVersionNeeded = 0x14; // from examining existing zip files bytes[i++] = (byte)(FixedVersionNeeded & 0x00FF); bytes[i++] = (byte)((FixedVersionNeeded & 0xFF00) >> 8); // bitfield Int16 BitField = 0x00; // from examining existing zip files bytes[i++] = (byte)(BitField & 0x00FF); bytes[i++] = (byte)((BitField & 0xFF00) >> 8); Int16 CompressionMethod = 0x00; // 0x08 = Deflate, 0x00 == No Compression // compression for directories = 0x00 (No Compression) if (!IsDirectory) { CompressionMethod = 0x08; // CRC32 (Int32) if (_FileData != null) { // If we have FileData, that means we've read this entry from an // existing zip archive. We must just copy the existing file data, // CRC, compressed size, and uncompressed size // over to the new (updated) archive. } else { // special case zero-length files System.IO.FileInfo fi = new System.IO.FileInfo(LocalFileName); if (fi.Length == 0) { CompressionMethod = 0x00; _UncompressedSize = 0; _CompressedSize = 0; _Crc32 = 0; } else { // Read in the data from the file in the filesystem, comress it, and // calculate a CRC on it as we read. CRC32 crc32 = new CRC32(); using (System.IO.Stream input = System.IO.File.OpenRead(LocalFileName)) { UInt32 crc = crc32.GetCrc32AndCopy(input, CompressedStream); _Crc32 = (Int32)crc; } CompressedStream.Close(); // to get the footer bytes written to the underlying stream _UncompressedSize = crc32.TotalBytesRead; _CompressedSize = (Int32)_UnderlyingMemoryStream.Length; // It is possible that applying this stream compression on a previously compressed // file will actually increase the size of the data. In that case, we back-off // and just store the uncompressed (really, already compressed) data. // We need to recompute the CRC, and point to the right data. if (_CompressedSize > _UncompressedSize) { using (System.IO.Stream input = System.IO.File.OpenRead(LocalFileName)) { _UnderlyingMemoryStream = new System.IO.MemoryStream(); UInt32 crc = crc32.GetCrc32AndCopy(input, _UnderlyingMemoryStream); _Crc32 = (Int32)crc; } _UncompressedSize = crc32.TotalBytesRead; _CompressedSize = (Int32)_UnderlyingMemoryStream.Length; if (_CompressedSize != _UncompressedSize) { throw new Exception("No compression but unequal stream lengths!"); } CompressionMethod = 0x00; } } } } // compression method bytes[i++] = (byte)(CompressionMethod & 0x00FF); bytes[i++] = (byte)((CompressionMethod & 0xFF00) >> 8); // LastMod bytes[i++] = (byte)(_LastModDateTime & 0x000000FF); bytes[i++] = (byte)((_LastModDateTime & 0x0000FF00) >> 8); bytes[i++] = (byte)((_LastModDateTime & 0x00FF0000) >> 16); bytes[i++] = (byte)((_LastModDateTime & 0xFF000000) >> 24); // calculated above bytes[i++] = (byte)(_Crc32 & 0x000000FF); bytes[i++] = (byte)((_Crc32 & 0x0000FF00) >> 8); bytes[i++] = (byte)((_Crc32 & 0x00FF0000) >> 16); bytes[i++] = (byte)((_Crc32 & 0xFF000000) >> 24); // CompressedSize (Int32) bytes[i++] = (byte)(_CompressedSize & 0x000000FF); bytes[i++] = (byte)((_CompressedSize & 0x0000FF00) >> 8); bytes[i++] = (byte)((_CompressedSize & 0x00FF0000) >> 16); bytes[i++] = (byte)((_CompressedSize & 0xFF000000) >> 24); // UncompressedSize (Int32) if (_Debug) { System.Console.WriteLine("Uncompressed Size: {0}", _UncompressedSize); } bytes[i++] = (byte)(_UncompressedSize & 0x000000FF); bytes[i++] = (byte)((_UncompressedSize & 0x0000FF00) >> 8); bytes[i++] = (byte)((_UncompressedSize & 0x00FF0000) >> 16); bytes[i++] = (byte)((_UncompressedSize & 0xFF000000) >> 24); // filename length (Int16) Int16 filenameLength = (Int16)FileName.Length; // see note below about TrimVolumeFromFullyQualifiedPaths. if ((TrimVolumeFromFullyQualifiedPaths) && (FileName[1] == ':') && (FileName[2] == '\\')) { filenameLength -= 3; } // apply upper bound to the length if (filenameLength + i > bytes.Length) { filenameLength = (Int16)(bytes.Length - (Int16)i); } bytes[i++] = (byte)(filenameLength & 0x00FF); bytes[i++] = (byte)((filenameLength & 0xFF00) >> 8); // extra field length (short) Int16 ExtraFieldLength = 0x00; bytes[i++] = (byte)(ExtraFieldLength & 0x00FF); bytes[i++] = (byte)((ExtraFieldLength & 0xFF00) >> 8); // Tue, 27 Mar 2007 16:35 // Creating a zip that contains entries with "fully qualified" pathnames // can result in a zip archive that is unreadable by Windows Explorer. // Such archives are valid according to other tools but not to explorer. // To avoid this, we can trim off the leading volume name and slash (eg // c:\) when creating (writing) a zip file. We do this by default and we // leave the old behavior available with the // TrimVolumeFromFullyQualifiedPaths flag - set it to false to get the old // behavior. It only affects zip creation. // actual filename char[] c = ((TrimVolumeFromFullyQualifiedPaths) && (FileName[1] == ':') && (FileName[2] == '\\')) ? FileName.Substring(3).ToCharArray() : // trim off volume letter, colon, and slash FileName.ToCharArray(); int j = 0; if (_Debug) { System.Console.WriteLine("local header: writing filename, {0} chars", c.Length); System.Console.WriteLine("starting offset={0}", i); } for (j = 0; (j < c.Length) && (i + j < bytes.Length); j++) { bytes[i + j] = System.BitConverter.GetBytes(c[j])[0]; if (_Debug) { System.Console.Write(" {0:X2}", bytes[i + j]); } } if (_Debug) { System.Console.WriteLine(); } i += j; // extra field (we always write nothing in this implementation) // ;; // remember the file offset of this header _RelativeOffsetOfHeader = (int)s.Length; if (_Debug) { System.Console.WriteLine("\nAll header data:"); for (j = 0; j < i; j++) { System.Console.Write(" {0:X2}", bytes[j]); } System.Console.WriteLine(); } // finally, write the header to the stream s.Write(bytes, 0, i); // preserve this header data for use with the central directory structure. _header = new byte[i]; if (_Debug) { System.Console.WriteLine("preserving header of {0} bytes", _header.Length); } for (j = 0; j < i; j++) { _header[j] = bytes[j]; } }
public void Close() { CompressedStream.Close(); }
private void WriteHeader(System.IO.Stream s, byte[] bytes) { // write the header info int i = 0; // signature bytes[i++] = (byte)(ZipEntrySignature & 0x000000FF); bytes[i++] = (byte)((ZipEntrySignature & 0x0000FF00) >> 8); bytes[i++] = (byte)((ZipEntrySignature & 0x00FF0000) >> 16); bytes[i++] = (byte)((ZipEntrySignature & 0xFF000000) >> 24); // version needed Int16 FixedVersionNeeded = 0x14; // from examining existing zip files bytes[i++] = (byte)(FixedVersionNeeded & 0x00FF); bytes[i++] = (byte)((FixedVersionNeeded & 0xFF00) >> 8); // bitfield Int16 BitField = 0x00; // from examining existing zip files bytes[i++] = (byte)(BitField & 0x00FF); bytes[i++] = (byte)((BitField & 0xFF00) >> 8); // compression method Int16 CompressionMethod = 0x08; // 0x08 = Deflate bytes[i++] = (byte)(CompressionMethod & 0x00FF); bytes[i++] = (byte)((CompressionMethod & 0xFF00) >> 8); // LastMod bytes[i++] = (byte)(_LastModDateTime & 0x000000FF); bytes[i++] = (byte)((_LastModDateTime & 0x0000FF00) >> 8); bytes[i++] = (byte)((_LastModDateTime & 0x00FF0000) >> 16); bytes[i++] = (byte)((_LastModDateTime & 0xFF000000) >> 24); // CRC32 (Int32) CRC32 crc32 = new CRC32(); UInt32 crc = 0; using (System.IO.Stream input = System.IO.File.OpenRead(FileName)) { crc = crc32.GetCrc32AndCopy(input, CompressedStream); } CompressedStream.Close(); // to get the footer bytes written to the underlying stream bytes[i++] = (byte)(crc & 0x000000FF); bytes[i++] = (byte)((crc & 0x0000FF00) >> 8); bytes[i++] = (byte)((crc & 0x00FF0000) >> 16); bytes[i++] = (byte)((crc & 0xFF000000) >> 24); // CompressedSize (Int32) Int32 isz = (Int32)_UnderlyingMemoryStream.Length; UInt32 sz = (UInt32)isz; bytes[i++] = (byte)(sz & 0x000000FF); bytes[i++] = (byte)((sz & 0x0000FF00) >> 8); bytes[i++] = (byte)((sz & 0x00FF0000) >> 16); bytes[i++] = (byte)((sz & 0xFF000000) >> 24); // UncompressedSize (Int32) if (_Debug) { System.Console.WriteLine("Uncompressed Size: {0}", crc32.TotalBytesRead); } bytes[i++] = (byte)(crc32.TotalBytesRead & 0x000000FF); bytes[i++] = (byte)((crc32.TotalBytesRead & 0x0000FF00) >> 8); bytes[i++] = (byte)((crc32.TotalBytesRead & 0x00FF0000) >> 16); bytes[i++] = (byte)((crc32.TotalBytesRead & 0xFF000000) >> 24); string internalFileName = IncludeDirectoryTree ? FileName : Path.GetFileName(FileName); // filename length (Int16) Int16 length = (Int16)internalFileName.Length; // see note below about TrimVolumeFromFullyQualifiedPaths. if ((TrimVolumeFromFullyQualifiedPaths) && (internalFileName[1] == ':') && (internalFileName[2] == '\\')) { length -= 3; } bytes[i++] = (byte)(length & 0x00FF); bytes[i++] = (byte)((length & 0xFF00) >> 8); // extra field length (short) Int16 ExtraFieldLength = 0x00; bytes[i++] = (byte)(ExtraFieldLength & 0x00FF); bytes[i++] = (byte)((ExtraFieldLength & 0xFF00) >> 8); // Tue, 27 Mar 2007 16:35 // Creating a zip that contains entries with "fully qualified" pathnames // can result in a zip archive that is unreadable by Windows Explorer. // Such archives are valid according to other tools but not to explorer. // To avoid this, we can trim off the leading volume name and slash (eg // c:\) when creating (writing) a zip file. We do this by default and we // leave the old behavior available with the // TrimVolumeFromFullyQualifiedPaths flag - set it to false to get the old // behavior. It only affects zip creation. // actual filename char[] c = ((TrimVolumeFromFullyQualifiedPaths) && (internalFileName[1] == ':') && (internalFileName[2] == '\\')) ? internalFileName.Substring(3).ToCharArray() : // trim off volume letter, colon, and slash internalFileName.ToCharArray(); int j = 0; if (_Debug) { System.Console.WriteLine("local header: writing filename, {0} chars", c.Length); System.Console.WriteLine("starting offset={0}", i); } for (j = 0; (j < c.Length) && (i + j < bytes.Length); j++) { bytes[i + j] = System.BitConverter.GetBytes(c[j])[0]; if (_Debug) { System.Console.Write(" {0:X2}", bytes[i + j]); } } if (_Debug) { System.Console.WriteLine(); } i += j; // extra field (we always write nothing in this implementation) // ;; // remember the file offset of this header _RelativeOffsetOfHeader = (int)s.Length; if (_Debug) { System.Console.WriteLine("\nAll header data:"); for (j = 0; j < i; j++) { System.Console.Write(" {0:X2}", bytes[j]); } System.Console.WriteLine(); } // finally, write the header to the stream s.Write(bytes, 0, i); // preserve this header data for use with the central directory structure. _header = new byte[i]; if (_Debug) { System.Console.WriteLine("preserving header of {0} bytes", _header.Length); } for (j = 0; j < i; j++) { _header[j] = bytes[j]; } }
private void WriteHeader(System.IO.Stream s, byte[] bytes) { // write the header info int i = 0; // signature bytes[i++] = (byte)(ZipEntrySignature & 0x000000FF); bytes[i++] = (byte)((ZipEntrySignature & 0x0000FF00) >> 8); bytes[i++] = (byte)((ZipEntrySignature & 0x00FF0000) >> 16); bytes[i++] = (byte)((ZipEntrySignature & 0xFF000000) >> 24); // version needed Int16 FixedVersionNeeded = 0x14; // from examining existing zip files bytes[i++] = (byte)(FixedVersionNeeded & 0x00FF); bytes[i++] = (byte)((FixedVersionNeeded & 0xFF00) >> 8); // bitfield Int16 BitField = 0x00; // from examining existing zip files bytes[i++] = (byte)(BitField & 0x00FF); bytes[i++] = (byte)((BitField & 0xFF00) >> 8); // compression method Int16 CompressionMethod = 0x08; // 0x08 = Deflate bytes[i++] = (byte)(CompressionMethod & 0x00FF); bytes[i++] = (byte)((CompressionMethod & 0xFF00) >> 8); // LastMod bytes[i++] = (byte)(_LastModDateTime & 0x000000FF); bytes[i++] = (byte)((_LastModDateTime & 0x0000FF00) >> 8); bytes[i++] = (byte)((_LastModDateTime & 0x00FF0000) >> 16); bytes[i++] = (byte)((_LastModDateTime & 0xFF000000) >> 24); // CRC32 (Int32) CRC32 crc32 = new CRC32(); UInt32 crc = 0; using (System.IO.Stream input = System.IO.File.OpenRead(FileName)) { crc = crc32.GetCrc32AndCopy(input, CompressedStream); } CompressedStream.Close(); // to get the footer bytes written to the underlying stream bytes[i++] = (byte)(crc & 0x000000FF); bytes[i++] = (byte)((crc & 0x0000FF00) >> 8); bytes[i++] = (byte)((crc & 0x00FF0000) >> 16); bytes[i++] = (byte)((crc & 0xFF000000) >> 24); // CompressedSize (Int32) Int32 isz = (Int32)_UnderlyingMemoryStream.Length; UInt32 sz = (UInt32)isz; bytes[i++] = (byte)(sz & 0x000000FF); bytes[i++] = (byte)((sz & 0x0000FF00) >> 8); bytes[i++] = (byte)((sz & 0x00FF0000) >> 16); bytes[i++] = (byte)((sz & 0xFF000000) >> 24); // UncompressedSize (Int32) bytes[i++] = (byte)(crc32.TotalBytesRead & 0x000000FF); bytes[i++] = (byte)((crc32.TotalBytesRead & 0x0000FF00) >> 8); bytes[i++] = (byte)((crc32.TotalBytesRead & 0x00FF0000) >> 16); bytes[i++] = (byte)((crc32.TotalBytesRead & 0xFF000000) >> 24); // filename length (Int16) Int16 length = (Int16)FileName.Length; bytes[i++] = (byte)(length & 0x00FF); bytes[i++] = (byte)((length & 0xFF00) >> 8); // extra field length (short) Int16 ExtraFieldLength = 0x00; bytes[i++] = (byte)(ExtraFieldLength & 0x00FF); bytes[i++] = (byte)((ExtraFieldLength & 0xFF00) >> 8); // actual filename char[] c = FileName.ToCharArray(); int j = 0; for (j = 0; (j < c.Length) && (i + j < bytes.Length); j++) { bytes[i + j] = System.BitConverter.GetBytes(c[j])[0]; } i += j; // extra field (we always write null in this implementation) // ;; // remember the file offset of this header _RelativeOffsetOfHeader = (int)s.Length; // finally, write the header to the stream s.Write(bytes, 0, i); // preserve this header data for use with the central directory structure. _header = new byte[i]; for (j = 0; j < i; j++) { _header[j] = bytes[j]; } }