filestream.cs

来自「没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没」· CS 代码 · 共 911 行 · 第 1/2 页

CS
911
字号
/* * FileStream.cs - Implementation of the "System.IO.FileStream" class. * * Copyright (C) 2001, 2003  Southern Storm Software, Pty Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */namespace System.IO{using System;using System.Security;using System.Threading;using Platform;public class FileStream : Stream{	// Default buffer size used for files.	internal const int BUFSIZ = 4096;	// Invalid handle value.	private static readonly IntPtr invalidHandle =		FileMethods.GetInvalidHandle();	// Internal state.	private IntPtr handle;	private FileAccess access;	private bool ownsHandle;	private bool isAsync;	private String path;	// Buffer information.	private int bufferSize;	private byte[] buffer;	private int bufferPosn;	private int bufferLen;	private long position;	private bool bufferOwnedByWrite;	private bool canSeek;	// Constructor.	public FileStream(String path, FileMode mode)			: this(path, mode, FileAccess.ReadWrite,				   FileShare.Read, BUFSIZ, false)			{				// Nothing to do here.			}	public FileStream(String path, FileMode mode, FileAccess access)			: this(path, mode, access, FileShare.Read, BUFSIZ, false)			{				// Nothing to do here.			}	public FileStream(String path, FileMode mode,					  FileAccess access, FileShare share)			: this(path, mode, access, share, BUFSIZ, false)			{				// Nothing to do here.			}	public FileStream(String path, FileMode mode,					  FileAccess access, FileShare share,					  int bufferSize)			: this(path, mode, access, share, bufferSize, false)			{				// Nothing to do here.			}	public FileStream(String path, FileMode mode,					  FileAccess access, FileShare share,					  int bufferSize, bool useAsync)			{				// Validate the parameters.				if(path == null)				{					throw new ArgumentNullException("path");				}				if(!FileMethods.ValidatePathname(path))				{					throw new ArgumentException(_("IO_InvalidPathname"));				}				if(bufferSize <= 0)				{					throw new ArgumentOutOfRangeException						("bufferSize", _("ArgRange_BufferSize"));				}				if(access < FileAccess.Read ||				   access > FileAccess.ReadWrite)				{					throw new ArgumentOutOfRangeException						("access", _("IO_FileAccess"));				}				if(mode < FileMode.CreateNew ||				   mode > FileMode.Append)				{					throw new ArgumentOutOfRangeException						("mode", _("IO_FileMode"));				}			#if ECMA_COMPAT				if((((int)share) & ~0x03) != 0)			#else				if((((int)share) & ~0x13) != 0)			#endif				{					throw new ArgumentOutOfRangeException						("share", _("IO_FileShare"));				}				// Attempt to open the file.				if(!FileMethods.Open(path, mode, access, share, out handle))				{					Errno errno = FileMethods.GetErrno();					if(errno == Errno.ENOENT)					{						//						// Under UNIX ENOENT is returned if the						// directory the file lives in doesn't exist.						// ECMA requires DirectoryNotFountException						// in that case.						//						String dirname = System.IO.Path.GetDirectoryName(path);						if (!System.IO.Directory.Exists(dirname))							throw new DirectoryNotFoundException();						throw new FileNotFoundException(null, path);					}					else if(errno == Errno.ENOTDIR)					{						throw new DirectoryNotFoundException();					}					else if(errno == Errno.ENAMETOOLONG)					{						throw new PathTooLongException();					}					else if(errno == Errno.EACCES)					{						throw new UnauthorizedAccessException();					}					else					{						throw new IOException(errno);					}				}				// Initialize the object state.				this.access = access;				this.ownsHandle = true;				this.isAsync = useAsync;				this.path = path;				this.bufferSize = bufferSize;				this.buffer = new byte [bufferSize];				this.bufferPosn = 0;				this.bufferLen = 0;				this.bufferOwnedByWrite = false;				this.canSeek = FileMethods.CanSeek(handle);				this.position = 0;			}	// Non-ECMA constructors.#if !ECMA_COMPAT	public FileStream(IntPtr handle, FileAccess access)			: this(handle, access, true, BUFSIZ, false)			{				// Nothing to do here.			}	public FileStream(IntPtr handle, FileAccess access, bool ownsHandle)			: this(handle, access, ownsHandle, BUFSIZ, false)			{				// Nothing to do here.			}	public FileStream(IntPtr handle, FileAccess access,					  bool ownsHandle, int bufferSize)			: this(handle, access, ownsHandle, bufferSize, false)			{				// Nothing to do here.			}	public FileStream(IntPtr handle, FileAccess access,					  bool ownsHandle, int bufferSize,					  bool isAsync)			{				// Validate the parameters.				if(bufferSize <= 0)				{					throw new ArgumentOutOfRangeException						("bufferSize", _("ArgRange_BufferSize"));				}				if(access < FileAccess.Read ||				   access > FileAccess.ReadWrite)				{					throw new ArgumentOutOfRangeException						("access", _("IO_FileAccess"));				}			#if false				if(!FileMethods.CheckHandleAccess(handle, access))				{					throw new UnauthorizedAccessException						(_("IO_IncorrectAccess"));				}			#endif				// Initialize the object state.				this.handle = handle;				this.access = access;				this.ownsHandle = ownsHandle;				this.isAsync = isAsync;				this.bufferSize = bufferSize;				this.buffer = new byte [bufferSize];				this.bufferPosn = 0;				this.bufferLen = 0;				this.bufferOwnedByWrite = false;				this.canSeek = FileMethods.CanSeek(handle);				if(canSeek)				{					this.position = FileMethods.Seek						(handle, 0, SeekOrigin.Current);				}				else				{					this.position = 0;				}			}	// Internal constructor used by IsolatedStorageFileStream.	internal FileStream(String path)			{				this.path = path;			}#endif	// Destructor.	~FileStream()			{				Dispose(false);			}	// Asynchronous operations - let the base class do the work.	public override IAsyncResult BeginRead				(byte[] buffer, int offset, int count,				 AsyncCallback callback, Object state)			{				return base.BeginRead(buffer, offset, count, callback, state);			}	public override int EndRead(IAsyncResult asyncResult)			{				return base.EndRead(asyncResult);			}	public override IAsyncResult BeginWrite				(byte[] buffer, int offset, int count,				 AsyncCallback callback, Object state)			{				return base.BeginWrite(buffer, offset, count, callback, state);			}	public override void EndWrite(IAsyncResult asyncResult)			{				base.EndWrite(asyncResult);			}	// Flush read data from the buffer.	private void FlushReadBuffer()			{				if(canSeek)				{					if(bufferPosn < bufferLen)					{						FileMethods.Seek(handle, -bufferPosn,										 SeekOrigin.Current);						position -= bufferPosn;					}					bufferPosn = 0;					bufferLen = 0;				}			}	// Flush any buffered write data to the file.	private void FlushWriteBuffer()			{				if(bufferPosn > 0)				{					if(!FileMethods.Write(handle, buffer, 0, bufferPosn))					{						throw new IOException							(FileMethods.GetErrno(), _("IO_WriteFailed"));					}					bufferPosn = 0;				}			}	// Set up for a read.	private void SetupRead()			{				if((access & FileAccess.Read) == 0)				{					throw new NotSupportedException						(_("IO_NotSupp_Read"));				}				if(handle == invalidHandle)				{					throw new ObjectDisposedException(_("IO_StreamClosed"));				}				if(bufferOwnedByWrite)				{					FlushWriteBuffer();					bufferOwnedByWrite = false;				}			}	// Set up for a write.	private void SetupWrite()			{				if((access & FileAccess.Write) == 0)				{					throw new NotSupportedException(_("IO_NotSupp_Write"));				}				if(handle == invalidHandle)				{					throw new ObjectDisposedException(_("IO_StreamClosed"));				}				if(!bufferOwnedByWrite)				{					FlushReadBuffer();					bufferOwnedByWrite = true;				}			}	// Close the stream.	public override void Close()			{				Dispose(true);				GC.SuppressFinalize(this);			}	// Dispose of this stream.	protected virtual void Dispose(bool disposing)			{				lock(this)				{					if(handle != invalidHandle)					{						if(bufferOwnedByWrite)						{							FlushWriteBuffer();						}						if(ownsHandle)						{							FileMethods.Close(handle);						}						handle = invalidHandle;					}				}			}	// Flush the pending contents in this stream.	public override void Flush()			{				lock(this)				{					if(handle != invalidHandle)					{						if(bufferOwnedByWrite)						{							FlushWriteBuffer();							if(!FileMethods.FlushWrite(handle))							{								throw new IOException									(FileMethods.GetErrno(),									_("IO_FlushFailed"));							}						}						else						{							FlushReadBuffer();						}					}					else					{						throw new ObjectDisposedException							(_("IO_StreamClosed"));					}				}			}	// Read data from this stream.	public override int Read(byte[] buffer, int offset, int count)			{				int readLen = 0;				int tempLen;				// Validate the parameters and setup the object for reading.				ValidateBuffer(buffer, offset, count);				// Lock down the file stream while we do this.				lock(this)				{					// Set up for the read operation.					SetupRead();					// Read data into the caller's buffer.					while(count > 0)					{						// How much data do we have available in the buffer?						tempLen = bufferLen - bufferPosn;						if(tempLen <= 0)						{							bufferPosn = 0;							bufferLen = FileMethods.Read								(handle, this.buffer, 0, bufferSize);							if(bufferLen < 0)							{								bufferLen = 0;								throw new IOException									(FileMethods.GetErrno(),									 _("IO_ReadFailed"));							}							else if(bufferLen == 0)							{								break;							}							else							{								tempLen = bufferLen;							}						}						// Don't read more than the caller wants.						if(tempLen > count)						{							tempLen = count;						}						// Copy stream data to the caller's buffer.						Array.Copy(this.buffer, bufferPosn,								   buffer, offset, tempLen);						// Advance to the next buffer positions.						readLen += tempLen;						offset += tempLen;						count -= tempLen;						bufferPosn += tempLen;						position += tempLen;					}				}				// Return the number of bytes that were read to the caller.				return readLen;			}	// Read a single byte from this stream.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?