using System; using System.IO; using System.Runtime.Remoting; using Developpez.Dotnet.Properties; namespace Developpez.Dotnet.IO { /// /// Wraps a stream for all operations except Close and Dispose, which /// merely flush the stream and prevent further operations from being /// carried out using this wrapper. /// /// Cette classe provient de la librairie MiscUtil créée par Jon Skeet /// http://www.yoda.arachsys.com/csharp/miscutil/ /// /// internal sealed class NonClosingStreamWrapper : Stream { #region Members specific to this wrapper class /// /// Creates a new instance of the class, wrapping the specified stream. /// /// The stream to wrap. Must not be null. /// stream is null public NonClosingStreamWrapper(Stream stream) { stream.CheckArgumentNull("stream"); this.stream = stream; } Stream stream; /// /// Stream wrapped by this wrapper /// public Stream BaseStream { get { return stream; } } /// /// Whether this stream has been closed or not /// bool closed = false; /// /// Throws an InvalidOperationException if the wrapper is closed. /// void CheckClosed() { if (closed) { throw new InvalidOperationException(ExceptionMessages.WrapperClosed); } } #endregion #region Overrides of Stream methods and properties /// /// Begins an asynchronous read operation. /// /// The buffer to read the data into. /// /// The byte offset in buffer at which to begin writing data read from the stream. /// /// The maximum number of bytes to read. /// /// An optional asynchronous callback, to be called when the read is complete. /// /// /// A user-provided object that distinguishes this particular /// asynchronous read request from other requests. /// /// /// An IAsyncResult that represents the asynchronous read, /// which could still be pending. /// public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { CheckClosed(); return stream.BeginRead(buffer, offset, count, callback, state); } /// /// Begins an asynchronous write operation. /// /// The buffer to write data from. /// The byte offset in buffer from which to begin writing. /// The maximum number of bytes to write. /// /// An optional asynchronous callback, to be called when the write is complete. /// /// /// A user-provided object that distinguishes this particular asynchronous /// write request from other requests. /// /// /// An IAsyncResult that represents the asynchronous write, /// which could still be pending. /// public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { CheckClosed(); return stream.BeginWrite(buffer, offset, count, callback, state); } /// /// Indicates whether or not the underlying stream can be read from. /// public override bool CanRead { get { return closed ? false : stream.CanRead; } } /// /// Indicates whether or not the underlying stream supports seeking. /// public override bool CanSeek { get { return closed ? false : stream.CanSeek; } } /// /// Indicates whether or not the underlying stream can be written to. /// public override bool CanWrite { get { return closed ? false : stream.CanWrite; } } /// /// This method is not proxied to the underlying stream; instead, the wrapper /// is marked as unusable for other (non-close/Dispose) operations. The underlying /// stream is flushed if the wrapper wasn't closed before this call. /// public override void Close() { if (!closed) { stream.Flush(); } closed = true; } /// /// Throws a NotSupportedException. /// /// The Type of the object that the new ObjRef will reference. /// n/a public override ObjRef CreateObjRef(Type requestedType) { throw new NotSupportedException(); } /// /// Waits for the pending asynchronous read to complete. /// /// /// The reference to the pending asynchronous request to finish. /// /// /// The number of bytes read from the stream, between zero (0) /// and the number of bytes you requested. Streams only return /// zero (0) at the end of the stream, otherwise, they should /// block until at least one byte is available. /// public override int EndRead(IAsyncResult asyncResult) { CheckClosed(); return stream.EndRead(asyncResult); } /// /// Ends an asynchronous write operation. /// /// A reference to the outstanding asynchronous I/O request. public override void EndWrite(IAsyncResult asyncResult) { CheckClosed(); stream.EndWrite(asyncResult); } /// /// Flushes the underlying stream. /// public override void Flush() { CheckClosed(); stream.Flush(); } /// /// Throws a NotSupportedException. /// /// n/a public override object InitializeLifetimeService() { throw new NotSupportedException(); } /// /// Returns the length of the underlying stream. /// public override long Length { get { CheckClosed(); return stream.Length; } } /// /// Gets or sets the current position in the underlying stream. /// public override long Position { get { CheckClosed(); return stream.Position; } set { CheckClosed(); stream.Position = value; } } /// /// Reads a sequence of bytes from the underlying stream and advances the /// position within the stream by the number of bytes read. /// /// /// An array of bytes. When this method returns, the buffer contains /// the specified byte array with the values between offset and /// (offset + count- 1) replaced by the bytes read from the underlying source. /// /// /// The zero-based byte offset in buffer at which to begin storing the data /// read from the underlying stream. /// /// /// The maximum number of bytes to be read from the /// underlying stream. /// /// The total number of bytes read into the buffer. /// This can be less than the number of bytes requested if that many /// bytes are not currently available, or zero (0) if the end of the /// stream has been reached. /// public override int Read(byte[] buffer, int offset, int count) { CheckClosed(); return stream.Read(buffer, offset, count); } /// /// Reads a byte from the stream and advances the position within the /// stream by one byte, or returns -1 if at the end of the stream. /// /// The unsigned byte cast to an Int32, or -1 if at the end of the stream. public override int ReadByte() { CheckClosed(); return stream.ReadByte(); } /// /// Sets the position within the current stream. /// /// A byte offset relative to the origin parameter. /// /// A value of type SeekOrigin indicating the reference /// point used to obtain the new position. /// /// The new position within the underlying stream. public override long Seek(long offset, SeekOrigin origin) { CheckClosed(); return stream.Seek(offset, origin); } /// /// Sets the length of the underlying stream. /// /// The desired length of the underlying stream in bytes. public override void SetLength(long value) { CheckClosed(); stream.SetLength(value); } /// /// Writes a sequence of bytes to the underlying stream and advances /// the current position within the stream by the number of bytes written. /// /// /// An array of bytes. This method copies count bytes /// from buffer to the underlying stream. /// /// /// The zero-based byte offset in buffer at /// which to begin copying bytes to the underlying stream. /// /// The number of bytes to be written to the underlying stream. public override void Write(byte[] buffer, int offset, int count) { CheckClosed(); stream.Write(buffer, offset, count); } /// /// Writes a byte to the current position in the stream and /// advances the position within the stream by one byte. /// /// The byte to write to the stream. public override void WriteByte(byte value) { CheckClosed(); stream.WriteByte(value); } #endregion } }