예제 #1
0
        /// <summary>
        /// Decompresses bytes for one file from an archive or archive chain,
        /// checking the crc at the end.
        /// </summary>
        private void UnpackFileBytes(
            IUnpackStreamContext streamContext,
            string fileName,
            long compressedSize,
            long uncompressedSize,
            uint crc,
            Stream fileStream,
            Func <Stream, Stream> compressionStreamCreator,
            ref Stream archiveStream)
        {
            CrcStream crcStream = new CrcStream(fileStream);

            ConcatStream concatStream = new ConcatStream(
                delegate(ConcatStream s)
            {
                this.currentArchiveBytesProcessed = s.Source.Position;
                streamContext.CloseArchiveReadStream(
                    this.currentArchiveNumber,
                    String.Empty,
                    s.Source);

                this.currentArchiveNumber--;
                this.OnProgress(ArchiveProgressType.FinishArchive);
                this.currentArchiveNumber        += 2;
                this.currentArchiveName           = null;
                this.currentArchiveBytesProcessed = 0;
                this.currentArchiveTotalBytes     = 0;

                s.Source = this.OpenArchive(streamContext, this.currentArchiveNumber);

                FileStream archiveFileStream = s.Source as FileStream;
                this.currentArchiveName      = (archiveFileStream != null ?
                                                Path.GetFileName(archiveFileStream.Name) : null);

                this.currentArchiveTotalBytes = s.Source.Length;
                this.currentArchiveNumber--;
                this.OnProgress(ArchiveProgressType.StartArchive);
                this.currentArchiveNumber++;
            });

            concatStream.Source = archiveStream;
            concatStream.SetLength(compressedSize);

            Stream decompressionStream = compressionStreamCreator(concatStream);

            try
            {
                byte[] buf            = new byte[4096];
                long   bytesRemaining = uncompressedSize;
                int    counter        = 0;
                while (bytesRemaining > 0)
                {
                    int count = (int)Math.Min(buf.Length, bytesRemaining);
                    count = decompressionStream.Read(buf, 0, count);
                    crcStream.Write(buf, 0, count);
                    bytesRemaining -= count;

                    this.fileBytesProcessed          += count;
                    this.currentFileBytesProcessed   += count;
                    this.currentArchiveBytesProcessed = concatStream.Source.Position;

                    if (++counter % 16 == 0) // Report every 64K
                    {
                        this.currentArchiveNumber--;
                        this.OnProgress(ArchiveProgressType.PartialFile);
                        this.currentArchiveNumber++;
                    }
                }
            }
            finally
            {
                archiveStream = concatStream.Source;
            }

            crcStream.Flush();

            if (crcStream.Crc != crc)
            {
                throw new ZipException("CRC check failed for file: " + fileName);
            }
        }
예제 #2
0
        /// <summary>
        /// Writes compressed bytes of one file to the archive,
        /// keeping track of the CRC and number of bytes written.
        /// </summary>
        private long PackFileBytes(
            IPackStreamContext streamContext,
            Stream fileStream,
            long maxArchiveSize,
            Func <Stream, Stream> compressionStreamCreator,
            ref Stream archiveStream,
            out uint crc)
        {
            long      writeStartPosition = archiveStream.Position;
            long      bytesWritten       = 0;
            CrcStream fileCrcStream      = new CrcStream(fileStream);

            ConcatStream concatStream = new ConcatStream(
                delegate(ConcatStream s)
            {
                Stream sourceStream = s.Source;
                bytesWritten       += sourceStream.Position - writeStartPosition;

                this.CheckArchiveWriteStream(
                    streamContext,
                    maxArchiveSize,
                    1,
                    ref sourceStream);

                writeStartPosition = sourceStream.Position;
                s.Source           = sourceStream;
            });

            concatStream.Source = archiveStream;

            if (maxArchiveSize > 0)
            {
                concatStream.SetLength(maxArchiveSize);
            }

            Stream compressionStream = compressionStreamCreator(concatStream);

            try
            {
                byte[] buf            = new byte[4096];
                long   bytesRemaining = fileStream.Length;
                int    counter        = 0;
                while (bytesRemaining > 0)
                {
                    int count = (int)Math.Min(
                        bytesRemaining, (long)buf.Length);

                    count = fileCrcStream.Read(buf, 0, count);
                    if (count <= 0)
                    {
                        throw new ZipException(
                                  "Failed to read file: " + this.currentFileName);
                    }

                    compressionStream.Write(buf, 0, count);
                    bytesRemaining -= count;

                    this.fileBytesProcessed          += count;
                    this.currentFileBytesProcessed   += count;
                    this.currentArchiveTotalBytes     = concatStream.Source.Position;
                    this.currentArchiveBytesProcessed = this.currentArchiveTotalBytes;

                    if (++counter % 16 == 0) // Report every 64K
                    {
                        this.OnProgress(ArchiveProgressType.PartialFile);
                    }
                }

                if (compressionStream is DeflateStream)
                {
#if CORECLR
                    compressionStream.Dispose();
#else
                    compressionStream.Close();
#endif
                }
                else
                {
                    compressionStream.Flush();
                }
            }
            finally
            {
                archiveStream = concatStream.Source;
            }

            bytesWritten += archiveStream.Position - writeStartPosition;

            crc = fileCrcStream.Crc;

            return(bytesWritten);
        }