Пример #1
0
        /// <summary>
        /// Adds the entry.
        /// </summary>
        /// <param name="entryName">Name of the entry.</param>
        /// <param name="stream">The stream.</param>
        public void AddEntry([NotNull] string entryName, [NotNull] Stream stream)
        {
            if (!stream.CanRead)
            {
                throw new ArgumentException("Stream should be readable");
            }

            // To do: assert whether entry name is unique and valid

            var entryInfo = new ZipEntryInfo();

            entryInfo.EntryName        = entryName;
            entryInfo.LastModifiedDate = DateTime.Now - new TimeSpan(1, 0, 0);
            Archive(stream, _outputStream, _tempFileStream, entryInfo, _encoding);
            _entriesCount++;
        }
Пример #2
0
        private static void Archive(Stream input, Stream output, Stream headerOutput, ZipEntryInfo additionalInfo, Encoding encoding)
        {
            var bytes = new byte[4096];

            long i = 0;

            // signature
            Write4Bytes(bytes, ref i, ZipConstants.ZipEntrySignature);

            // version needed
            short FixedVersionNeeded = 0x14; // from examining existing zip files

            Write2Bytes(bytes, ref i, FixedVersionNeeded);

            // bitfield
            short BitField = 0x00; // from examining existing zip files

            Write2Bytes(bytes, ref i, BitField);

            // compression method
            var   offsetOfCompression = output.Position + i;
            short CompressionMethod   = 0x08; // 0x08 = Deflate, 0x00 == No Compression

            Write2Bytes(bytes, ref i, CompressionMethod);

            // LastMod
            var _LastModDateTime = additionalInfo.LastModifiedDateInt;

            Write4Bytes(bytes, ref i, _LastModDateTime);

            // Writing zeros for Crc32, CompressedSize and UncompressedSize. Total length is 12 bytes
            // This fields will be filled later, after compression
            var offsetOfCrcAndSizesInHeader = i;
            var offsetOfCrcAndSizes         = output.Position + i;

            i += 12; // Increasing offset by 12.

            // filename length (Int16)
            var data   = encoding.GetBytes(additionalInfo.EntryName);
            var length = (short)data.Length;

            Write2Bytes(bytes, ref i, length);

            // extra field length (short)
            short ExtraFieldLength = 0x00;

            Write2Bytes(bytes, ref i, ExtraFieldLength);

            // actual filename
            Array.Copy(data, 0, bytes, i, data.Length);
            i += data.Length;

            // remember the file offset of this header
            long relativeOffsetOfHeader = (int)output.Position;

            // finally, write the header to the stream
            output.Write(bytes, 0, (int)i);

            var  crc32 = new CRC32();
            uint crc;
            var  fileDataOffset = output.Position;

            using (var compressedStream = new DeflateStream(output, CompressionMode.Compress, true))
            {
                crc = crc32.GetCrc32AndCopy(input, compressedStream);
            }

            var  compressedSize = output.Position - fileDataOffset;
            long originalSize   = crc32.TotalBytesRead;

            //if(originalSize == 0)
            //{
            //   SetNoCompression(output, offsetOfCompression);

            //   compressedSize = 0;
            //   crc = 0;
            //   output.Seek(fileDataOffset, SeekOrigin.Begin);
            //}

            // We don't need the input stream, so we close it
            input.Close();

            WriteCrcAndSizes(output, offsetOfCrcAndSizes, crc, originalSize, compressedSize);

            // Copying crc, originalSize, compressedSize to the bytes. In order to be used in central directory structure
            var k = offsetOfCrcAndSizesInHeader;

            Write4Bytes(bytes, ref k, (int)crc);
            Write4Bytes(bytes, ref k, (int)compressedSize);
            Write4Bytes(bytes, ref k, (int)originalSize);

            var header = new byte[i];

            Array.Copy(bytes, header, i);

            WriteCenralDirectoryFileHeader(headerOutput, header, relativeOffsetOfHeader);
        }