Пример #1
0
        /// <summary>
        /// 将若干压缩缩的字节读入指定的字节数组。
        /// </summary>
        /// <param name="buffer">用于存储压缩缩的字节的数组。</param>
        /// <param name="offset">数组中开始读取的位置。</param>
        /// <param name="count">读取的压缩缩字节数。</param>
        /// <returns>压缩缩到字节数组中的字节数。</returns>
        /// <remarks>
        ///     <para>
        /// 如果需要使用 <c>DeflateStream</c> 在读取时同步解压, 可以设置解压模式到 <c>CompressionMode.Compress</c>。然后使用 Read() 方法读取并解压。
        /// 如果需要使用 <c>DeflateStream</c> 在读取时同步压缩, 可以设置解压模式到 <c>CompressionMode.DeCompress</c>。然后使用 Read() 方法读取并解压。
        /// </para>
        ///     <para>
        /// 一个 <c>DeflateStream</c> 只能用于 <c>Read()</c> 或 <c>Write()</c>, 但不能同时读写。
        /// </para>
        /// </remarks>
        /// <exception cref="ZlibException">已经执行过 Write() 。</exception>
        /// <exception cref="T:System.ArgumentException">
        ///     <paramref name="offset"/> 与 <paramref name="count"/> 的和大于缓冲区长度。</exception>
        /// <exception cref="T:System.ArgumentNullException">
        ///     <paramref name="buffer"/> 为 null。</exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">
        ///     <paramref name="offset"/> 或 <paramref name="count"/> 为负。</exception>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。</exception>
        /// <exception cref="T:System.NotSupportedException">流不支持读取。</exception>
        /// <exception cref="T:System.ObjectDisposedException">在流关闭后调用方法。</exception>
        public override int Read(byte[] buffer, int offset, int count)
        {
            // According to MS documentation, any implementation of the IO.Stream.Read function must:
            // (a) throw an exception if offset & count reference an invalid part of the buffer,
            //     or if count < 0, or if buffer is null
            // (b) return 0 only upon EOF, or if count = 0
            // (c) if not EOF, then return at least 1 byte, up to <count> bytes

            Thrower.CheckArgumentException(buffer, offset, count);
            Thrower.ThrowObjectDisposedExceptionIf(IsDisposed, TypeName);
            if (_streamMode == StreamMode.Undefined)
            {
                Thrower.ThrowNotSupportedExceptionIf(!_stream.CanRead, "流不支持读取。");

                _streamMode = StreamMode.Reader;

                ZlibCodec.AvailableBytesIn = 0;
            }

            ValidStreamMode(StreamMode.Reader);
            if (count == 0)
            {
                return(0);
            }
            if (_noMore && WantCompress)
            {
                return(0);
            }

            Thrower.ThrowArgumentNullExceptionIf(buffer, "buffer");
            Thrower.ThrowArgumentOutOfRangeExceptionIf(count <0 || (offset + count)> buffer.GetLength(0), "count");
            Thrower.ThrowArgumentOutOfRangeExceptionIf(offset < buffer.GetLowerBound(0), "offset");

            ZlibState rc;

            // set up the output of the deflate/inflate codec:
            _z.OutputBuffer      = buffer;
            _z.NextOut           = offset;
            _z.AvailableBytesOut = count;

            // This is necessary in case _workingBuffer has been resized. (new byte[])
            // (The first reference to _workingBuffer goes through the private accessor which
            // may initialize it.)
            _z.InputBuffer = WorkingBuffer;

            do
            {
                // need data in _workingBuffer in order to deflate/inflate.  Here, we check if we have any.
                if ((_z.AvailableBytesIn == 0) && (!_noMore))
                {
                    // No data available, so try to Read data from the captive stream.
                    _z.NextIn           = 0;
                    _z.AvailableBytesIn = _stream.Read(_workingBuffer, 0, _workingBuffer.Length);
                    if (_z.AvailableBytesIn == 0)
                    {
                        _noMore = true;
                    }
                }
                // we have data in InputBuffer; now compress or decompress as appropriate
                rc = (WantCompress)
                    ? _z.Deflate(_flushMode)
                    : _z.Inflate(_flushMode);

                if (_noMore && (rc == ZlibState.BufferError))
                {
                    return(0);
                }

                if (rc != ZlibState.Success && rc != ZlibState.StreamEnd)
                {
                    throw new ZlibException(Py.Core.Str.FormatX("{0}:  结果={1} 信息={2}", (WantCompress ? "压缩" : "解压"), rc, _z.Message));
                }

                if ((_noMore || rc == ZlibState.StreamEnd) && (_z.AvailableBytesOut == count))
                {
                    break; // nothing more to read
                }
            }  while (_z.AvailableBytesOut > 0 && !_noMore && rc == ZlibState.Success);


            // workitem 8557
            // is there more room in output?
            if (_z.AvailableBytesOut > 0)
            {
                if (rc == ZlibState.Success && _z.AvailableBytesIn == 0)
                {
                    // deferred
                }

                // are we completely done reading?
                if (_noMore)
                {
                    // and in compression?
                    if (WantCompress)
                    {
                        // no more input data available; therefore we flush to
                        // try to complete the read
                        rc = _z.Deflate(FlushType.Finish);

                        if (rc != ZlibState.Success && rc != ZlibState.StreamEnd)
                        {
                            throw new ZlibException(String.Format("压缩:   状态={0}  消息={1}", rc, _z.Message));
                        }
                    }
                }
            }


            return(count - _z.AvailableBytesOut);
        }