现在的位置: 首页 > 综合 > 正文

System.IO.Stream

2014年03月12日 ⁄ 综合 ⁄ 共 7667字 ⁄ 字号 评论关闭
// ==++==
// 
//   
//    Copyright (c) 2002 Microsoft Corporation.  All rights reserved.
//   
//    The use and distribution terms for this software are contained in the file
//    named license.txt, which can be found in the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by the
//    terms of this license.
//   
//    You must not remove this notice, or any other, from this software.
//   
// 
// ==--==
/*============================================================
**
** Class:  Stream
**
**                                                    
**
** Purpose: Abstract base class for all Streams.  Provides
** default implementations of asynchronous reads & writes, in
** terms of the synchronous reads & writes (and vice versa).
**
** Date:  February 15, 2000
**
===========================================================*/
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Security;


namespace System.IO {
    /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream"]/*' />
    [Serializable()]
    public abstract class Stream : MarshalByRefObject, IDisposable {

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.Null"]/*' />
        public static readonly Stream Null = new NullStream();

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.CanRead"]/*' />
        public abstract bool CanRead {
            get;
        }

        // If CanSeek is false, Position, Seek, Length, and SetLength should throw.
        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.CanSeek"]/*' />
        public abstract bool CanSeek {
            get;
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.CanWrite"]/*' />
        public abstract bool CanWrite {
            get;
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.Length"]/*' />
        public abstract long Length {
            get;
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.Position"]/*' />
        public abstract long Position {
            get;
            set;
        }


        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.Close"]/*' />
        public virtual void Close()
        {
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.IDisposable.Dispose"]/*' />
        /// <internalonly/>
        void IDisposable.Dispose()
        {
            Close();
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.Flush"]/*' />
        public abstract void Flush();


        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.CreateWaitHandle"]/*' />
        protected virtual WaitHandle CreateWaitHandle()
        {
            return new ManualResetEvent(false);
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.BeginRead"]/*' />
        public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
        {
            if (!CanRead) __Error.ReadNotSupported();

            // To avoid a race with a stream's position pointer & generating race 
            // conditions with internal buffer indexes in our own streams that 
            // don't natively support async IO operations when there are multiple 
            // async requests outstanding, we will block the application's main
            // thread and do the IO synchronously.  
            SynchronousAsyncResult asyncResult = new SynchronousAsyncResult(state, false);
            try {
                int numRead = Read(buffer, offset, count);
                asyncResult._numRead = numRead;
                asyncResult._isCompleted = true;
                asyncResult._waitHandle.Set();
            }
            catch (IOException e) {
                asyncResult._exception = e;
            }
            
            if (callback != null)
                callback(asyncResult);

            return asyncResult;
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.EndRead"]/*' />
        public virtual int EndRead(IAsyncResult asyncResult)
        {
            if (asyncResult == null)
                throw new ArgumentNullException("asyncResult");

            SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
            if (ar == null || ar.IsWrite)
                __Error.WrongAsyncResult();
            if (ar._EndXxxCalled)
                __Error.EndReadCalledTwice();
            ar._EndXxxCalled = true;

            if (ar._exception != null)
                throw ar._exception;

            return ar._numRead;
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.BeginWrite"]/*' />
        public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
        {
            if (!CanWrite) __Error.WriteNotSupported();

            // To avoid a race with a stream's position pointer & generating race 
            // conditions with internal buffer indexes in our own streams that 
            // don't natively support async IO operations when there are multiple 
            // async requests outstanding, we will block the application's main
            // thread and do the IO synchronously.  
            SynchronousAsyncResult asyncResult = new SynchronousAsyncResult(state, true);
            try {
                Write(buffer, offset, count);
                asyncResult._isCompleted = true;
                asyncResult._waitHandle.Set();
            }
            catch (IOException e) {
                asyncResult._exception = e;
            }
            
            if (callback != null)
                callback.BeginInvoke(asyncResult, null, null);

            return asyncResult;
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.EndWrite"]/*' />
        public virtual void EndWrite(IAsyncResult asyncResult)
        {
            if (asyncResult==null)
                throw new ArgumentNullException("asyncResult");

            SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
            if (ar == null || !ar.IsWrite)
                __Error.WrongAsyncResult();
            if (ar._EndXxxCalled)
                __Error.EndWriteCalledTwice();
            ar._EndXxxCalled = true;

            if (ar._exception != null)
                throw ar._exception;
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.Seek"]/*' />
        public abstract long Seek(long offset, SeekOrigin origin);

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.SetLength"]/*' />
        public abstract void SetLength(long value);

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.Read"]/*' />
        public abstract int Read([In, Out] byte[] buffer, int offset, int count);

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.ReadByte"]/*' />
        public virtual int ReadByte()
        {
            // Reads one byte from the stream by calling Read(byte[], int, int). 
            // Will return an unsigned byte cast to an int or -1 on end of stream.
            // The performance of the default implementation on Stream is bad,
            // and any subclass with an internal buffer should override this method.
            byte[] oneByteArray = new byte[1];
            int r = Read(oneByteArray, 0, 1);
            if (r==0)
                return -1;
            return oneByteArray[0];
        }

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.Write"]/*' />
        public abstract void Write(byte[] buffer, int offset, int count);

        /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.WriteByte"]/*' />
        public virtual void WriteByte(byte value)
        {
            // Writes one byte from the stream by calling Write(byte[], int, int).  
            // The performance of the default implementation on Stream is bad,
            // and any subclass with an internal buffer should override this method.
            byte[] oneByteArray = new byte[1];
            oneByteArray[0] = value;
            Write(oneByteArray, 0, 1);
        }

        // No data, no need to serialize
        private class NullStream : Stream
        {
            protected internal NullStream() {}

            /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.NullStream.CanRead"]/*' />
            public override bool CanRead {
                get { return true; }
            }

            /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.NullStream.CanWrite"]/*' />
            public override bool CanWrite {
                get { return true; }
            }

            /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.NullStream.CanSeek"]/*' />
            public override bool CanSeek {
                get { return true; }
            }

            /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.NullStream.Length"]/*' />
            public override long Length {
                get { return 0; }
            }

            /// <include file='doc/Stream.uex' path='docs/doc[@for="Stream.NullStream.Position"]/*' />
            public override long Position {
                get { return 0; }
                set {}
            }

            public override void Close()
            {
            }

            public override void Flush()
            {
            }

            public override int Read([In, Out] byte[] buffer, int offset, int count)
            {
                return 0;
            }

            public override void Write(byte[] buffer, int offset, int count)
            {
            }

            public override long Seek(long offset, SeekOrigin origin)
            {
                return 0;
            }

            public override void SetLength(long length)
            {
            }
        }

        // Used as the IAsyncResult object when using asynchronous IO methods
        // on the base Stream class.  Note I'm not using async delegates, so
        // this is necessary.
        private sealed class SynchronousAsyncResult : IAsyncResult
        {
            internal ManualResetEvent _waitHandle;
            internal Object _stateObject;
            internal int _numRead;
            internal bool _isCompleted;
            internal bool _isWrite;
            internal bool _EndXxxCalled;
            internal Exception _exception;

            internal SynchronousAsyncResult(Object asyncStateObject, bool isWrite)
            {
                _stateObject = asyncStateObject;
                _isWrite = isWrite;
                _waitHandle = new ManualResetEvent(false);
            }

            public bool IsCompleted {
                get { return _isCompleted; }
            }

            public WaitHandle AsyncWaitHandle {
                get { return _waitHandle; }
            }

            public Object AsyncState {
                get { return _stateObject; }
            }

            public bool CompletedSynchronously {
                get { return true; }
            }

            internal bool IsWrite {
                get { return _isWrite; }
            }
        }
    }
}

抱歉!评论已关闭.