'Classes/System/IO/FileStream.ab Namespace System Namespace IO /* (handle As IntPtr, access As FileAccess) (handle As IntPtr, access As FileAccess, ownsHandle As Boolean) (handle As IntPtr, access As FileAccess, ownsHandle As Boolean) (handle As IntPtr, access As FileAccess, ownsHandle As Boolean, isAsync As Boolean) (path As String, mode As FileMode) (path As String, mode As FileMode, access As FileAccess) (path As String, mode As FileMode, access As FileAccess, share As FileShare, useAsync As Boolean) (path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions) (path As String, mode As FileMode, rights As FileSystemRights, share As FileShare, options As FileOptions) */ Class FileStream Inherits Stream Protected Sub initialize(ac As DWord, owns As Boolean, isAsync As Boolean) Imports ActiveBasic ownsHandle = owns If (ac And GENERIC_READ) = 0 Then readFn = New Detail.Unreadable End If If (ac And GENERIC_WRITE) = 0 Then writeFn = New Detail.Unwritable End If If GetFileType(handle) <> FILE_TYPE_DISK Then seekFn = New Detail.Unseekable End If If isAsync Then If IsNothing(seekFn) Then seekFn = New Detail.OverlappedSeekable End If If IsNothing(readFn) Then readFn = New Detail.OverlappedReadable End If If IsNothing(writeFn) Then writeFn = New Detail.OverlappedWritable End If Else If IsNothing(seekFn) Then seekFn = New Detail.Seekable End If If IsNothing(readFn) Then readFn = New Detail.Readable End If If IsNothing(writeFn) Then writeFn = New Detail.Writable End If End If End Sub Sub openFile(path As String, mode As FileMode, rights As DWord, share As FileShare, ByRef options As FileOptions) Imports ActiveBasic If IsNothing(path) Then Throw New ArgumentNullException("path") ElseIf path.Length = 0 Then Throw New ArgumentException("path.Length = 0") End If Dim sh = share As DWord Dim mo = mode As DWord Dim op = options As DWord If mode = FileMode.Append Then mo = OPEN_ALWAYS seekFn = New Detail.Unseekable End If Dim os = Environment.OSVersion Dim platform = os.Platform As DWord If platform = PlatformID.Win32Windows As DWord Or platform = PlatformID.Win32S As DWord Then options = (op As DWord And Not FILE_FLAG_OVERLAPPED) As FileOptions End If handle = CreateFile(ToTCStr(path), rights, sh, ByVal NULL, mo, op, 0) If handle = INVALID_HANDLE_VALUE Then 'エラー処理 'Throw ArgumentException 'Throw IOException 'Throw System.IO.FileNotFoundException handle = 0 Detail.ThrowWinLastErrorIOException("Failed to open/create file.") End If filePath = path If mode = FileMode.Append Then Seek(0, SeekOrigin.End) End If End Sub Sub initWithOpen(path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions) openFile(path, mode, access As DWord, share, options) initialize(access, True, UseOverlappled(options)) End Sub Sub initWithOpen2(path As String, mode As FileMode, rights As DWord, share As FileShare, options As FileOptions) openFile(path, mode, rights, share, options) Dim ac = 0 As DWord If (rights And GENERIC_READ) Or (rights And FILE_READ_DATA) Then ac = (ac As DWord Or GENERIC_READ) As FileAccess End If If (rights And GENERIC_WRITE) Or (rights And FILE_WRITE_DATA) Then ac = (ac As DWord Or GENERIC_WRITE) As FileAccess End If initialize(ac, True, UseOverlappled(options)) End Sub Static Function UseOverlappled(options As FileOptions) As Boolean Dim op = options As DWord If op And FILE_FLAG_OVERLAPPED Then UseOverlappled = True Else UseOverlappled = False End If End Function Sub FileStream() End Sub Public /*! @brief ファイルを開く。 @param[in] path ファイルパス @param[in] mode 開き方 @param[in] rights 使用するアクセス権の指定 @param[in] share 共有方法 @param[in] option オプション @date 2008/08/21 @auther Egtra */ Sub FileStream(path As String, mode As FileMode, rights As Security.AccessControl.FileSystemRights, share As FileShare, options As FileOptions) initWithOpen2(path, mode, rights As DWord, share, options) End Sub /*! @brief ファイルを開く。 @param[in] path ファイルパス @param[in] mode 開き方 @param[in] access ファイルアクセスの指定 @param[in] share 共有方法 @param[in] option オプション */ Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions) initWithOpen(path, mode, access, share, options) End Sub /*! @brief ファイルを開く。 @param[in] path ファイルパス @param[in] mode 開き方 @param[in] access ファイルアクセスの指定 @param[in] share 共有方法 @param[in] useAsync 非同期にするならTrue @date 2008/08/21 @auther Egtra */ Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare, useAsync As Boolean) Dim options = FileOptions.None If useAsync Then options = FileOptions.Asynchronous End If initWithOpen(path, mode, access, share, options) End Sub /*! @brief ファイルを開く。 @param[in] path ファイルパス @param[in] mode 開き方 @param[in] access ファイルアクセスの指定 @param[in] share 共有方法 */ Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare) initWithOpen(path,mode,access,share,FileOptions.None) End Sub /*! @brief ファイルを開く。 @param[in] path ファイルパス @param[in] mode 開き方 @param[in] access ファイルアクセスの指定 */ Sub FileStream(path As String, mode As FileMode, access As FileAccess) initWithOpen(path,mode,access,FileShare.None,FileOptions.None) End Sub /*! @brief ファイルを開く。 @param[in] path ファイルパス @param[in] mode 開き方 */ Sub FileStream(path As String, mode As FileMode) Dim access As FileAccess Select Case mode Case FileMode.Append access=FileAccess.Write Case FileMode.Create access=FileAccess.ReadWrite Case FileMode.CreateNew access=FileAccess.ReadWrite Case FileMode.Open access=FileAccess.ReadWrite Case FileMode.OpenOrCreate access=FileAccess.ReadWrite Case FileMode.Truncate access=FileAccess.Write End Select initWithOpen(path,mode,access,FileShare.None,FileOptions.None) End Sub /*! @brief 既存ハンドルを基にストリームを作る。 @param[in] h ハンドル @param[in] access ファイルアクセスの指定 @param[in] owns 所有権を保持するかどうか(TrueならDispose時に基のハンドルも閉じる) @param[in] isAsync 重複IOを使用するかどうか @date 2008/02/26 @auther Egtra @todo SafeFileHandle版に置き換えること */ Sub FileStream(h As HANDLE, access As FileAccess, owns = True As Boolean, isAsync = False As Boolean) handle = h initialize(access, owns, isAsync) End Sub Public /*! @brief ファイルが読み込みに対応しているかを返す */ Override Function CanRead() As Boolean Return readFn.CanRead End Function /*! @brief ファイルがシークに対応しているかを返す */ Override Function CanSeek() As Boolean Return seekFn.CanSeek End Function /*! @brief ファイルが書き込みに対応しているかを返す */ Override Function CanWrite() As Boolean Return writeFn.CanWrite End Function /*! @brief 保持しているハンドルを返す */ Function Handle() As HANDLE Return handle End Function Override Function Length() As QWord disposedCheck() Length = seekFn.Length(This) End Function Function Name() As String Return This.filePath End Function Override Sub Position(value As QWord) disposedCheck() seekFn.Position(This, value) End Sub Override Function Position() As QWord disposedCheck() Position = seekFn.Position(This) End Function Public /* Safe〜Handle系の実装は要相談!! */ /* Function SafeFileHandle() As SafeFileHandle End Function*/ Public Override Function BeginRead(buffer As *Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult disposedCheck() If buffer = 0 Then Throw New ArgumentNullException("FileStream.BeginRead", "buffer") End If BeginRead = readFn.BeginRead(This, buffer, offset, count, callback, state) End Function Override Function BeginWrite(buffer As *Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult disposedCheck() If buffer = 0 Then Throw New ArgumentNullException("FileStream.BeginWrite", "buffer") End If BeginWrite = writeFn.BeginWrite(This, buffer, offset, count, callback, state) End Function Override Function EndRead(asyncResult As System.IAsyncResult) As Long disposedCheck() EndRead = readFn.EndRead(This, asyncResult) End Function Override Sub EndWrite(asyncResult As System.IAsyncResult) disposedCheck() writeFn.EndWrite(This, asyncResult) End Sub Override Sub Flush() disposedCheck() Dim ret = FlushFileBuffers(This.handle) If ret = FALSE Then Detail.ThrowWinLastErrorIOException("FileStream.Flush: Failed to flush.") End If End Sub /* Function GetAccessControl() As FileSecurity FileSecurityの実装がまだできてない。 End Function*/ Sub Lock(position As QWord, length As QWord) disposedCheck() If position < 0 Then Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.UInt64(position), "position") ElseIf length < 0 Then Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.UInt64(length), "length") End If If LockFile(handle, LODWORD(position), HIDWORD(position), LODWORD(length), HIDWORD(length)) = FALSE Then Detail.ThrowWinLastErrorIOException("FileStream.Lock: Failed to lock.") End If End Sub Override Function Read(buffer As *Byte, offset As Long, count As Long) As Long disposedCheck() If buffer = 0 Then Throw New ArgumentNullException("FileStream.Read", "buffer") End If Read = readFn.Read(This, buffer, offset, count) End Function /*! @brief ストリームの現在位置を移動させる。 @param[in] offset originからの移動量 @param[in] origin 移動の基準位置 @return 移動後の新しい現在位置 @exception DisposedException 既にストリームが閉じられている場合 @exception ArgumentException 移動後の位置が負の位置(ファイル先頭より手前)になる場合 @exception IOException その他エラーが発生した場合 */ Override Function Seek(offset As Int64, origin As SeekOrigin) As Int64 disposedCheck() Seek = seekFn.Seek(This, offset, origin) End Function /* Sub SetAccessControl(fileSecurity As FileSecurity) FileSecurityの実装がまだできてない。 End Sub*/ Override Sub SetLength(value As QWord) disposedCheck() seekFn.SetLength(This, value) End Sub Override Function ToString() As String Return This.Name() End Function Sub Unlock(position As QWord, length As QWord) disposedCheck() Dim ret = UnlockFile(handle, LODWORD(position), HIDWORD(position), LODWORD(length), HIDWORD(length)) If ret = FALSE Then Detail.ThrowWinLastErrorIOException("FileStream.Unlock failed") End If End Sub Override Sub Write(buffer As *Byte, offset As Long, count As Long) disposedCheck() If buffer = 0 Then Throw New ArgumentNullException("FileStream.Write", "buffer") End If writeFn.Write(This, buffer, offset, count) End Sub Protected Override Sub Dispose(disposing As Boolean) If handle <> 0 Then CloseHandle(InterlockedExchangePointer(ByVal VarPtr(handle), NULL)) End If End Sub Sub disposedCheck() If handle = 0 Then Throw New ObjectDisposedException("FileStream: This stream has already closed.") End If End Sub Private handle As HANDLE seekFn As Detail.SeekFunctions readFn As Detail.ReadFunctions writeFn As Detail.WriteFunctions filePath As String ownsHandle As Boolean End Class End Namespace End Namespace