/// <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); }