Namespace System Namespace IO /* ほんとはmiscに入れるかかファイルを分けたほうがいいかもしれないが一先ず実装 */ Enum FileOptions Asynchronous DeleteOnClose Encrypted None RandomAccess SequentialScan WriteThrough End Enum Class FileStream Inherits Stream handle As HANDLE /* ファイルハンドルからこれらを取得できれば、これらは入らないが 今のところは不明なので自前で実装するしかない */ filePath As String fileMode As DWord fileAccess As DWord fileShare As DWord fileOptions As DWord fileReadOverlapped As OVERLAPPED fileWriteOverlapped As OVERLAPPED Public /* コンストラクタ.NETと同じように実装は難しい、一先ず動くものを実装したが変更が必要だと思う */ Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions) Dim ac As DWord Dim mo As DWord Dim sh As DWord Dim op As DWord Select Case access Case FileAccess.Read ac=GENERIC_READ Case FileAccess.ReadWrite ac=GENERIC_READ or GENERIC_WRITE Case FileAccess.Write ac=GENERIC_WRITE End Select Select Case share Case FileShare.DeleteFile sh=FILE_SHARE_DELETE Case FileShare.None sh=0 Case FileShare.Read sh=FILE_SHARE_READ Case FileShare.ReadWrite sh=FILE_SHARE_READ or FILE_SHARE_WRITE Case FileShare.Write sh=FILE_SHARE_WRITE End Select Select Case mode Case FileMode.Append mo=OPEN_ALWAYS Case FileMode.Create mo=CREATE_ALWAYS Case FileMode.CreateNew mo=CREATE_NEW Case FileMode.Open mo=OPEN_EXISTING Case FileMode.OpenOrCreate mo=OPEN_ALWAYS Case FileMode.Truncate mo=TRUNCATE_EXISTING End Select Select Case options Case FileOptions.Asynchronous op=FILE_FLAG_OVERLAPPED Case FileOptions.DeleteOnClose op=FILE_FLAG_DELETE_ON_CLOSE Case FileOptions.Encrypted Case FileOptions.None op=0 Case FileOptions.RandomAccess op=FILE_FLAG_RANDOM_ACCESS Case FileOptions.SequentialScan op=FILE_FLAG_SEQUENTIAL_SCAN Case FileOptions.WriteThrough op=FILE_FLAG_WRITE_THROUGH End Select This.handle=CreateFile(path As PSTR,ac,sh,ByVal NULL,mo,op,0) If This.handle=INVALID_HANDLE_VALUE Then 'エラー処理 'Throw ArgumentException 'Throw IOException 'Throw System.IO.FileNotFoundException This.handle=0 Beep(220,500) Exit Sub End If This.filePath = path This.fileMode = mo This.fileAccess = ac This.fileShare = sh This.fileOptions = op End Sub Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare) This.FileStream(path,mode,access,share,FileOptions.None) End Sub Sub FileStream(path As String, mode As FileMode, access As FileAccess) This.FileStream(path,mode,access,FileShare.None,FileOptions.None) End Sub 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 This.FileStream(path,mode,access,FileShare.None,FileOptions.None) End Sub Sub ~FileStream() This.Flush() This.Close() End Sub Public Override Function CanRead() As Boolean /* ファイルが読み込みに対応しているかを返す */ If This.fileAccess And GENERIC_READ Then Return True Else Return False End If End Function Override Function CanSeek() As Boolean /* ファイルがシークに対応しているかを返す */ If GetFileType(This.handle)=FILE_TYPE_DISK Then Return True Else Return False End If End Function ' Override Function CanTimeout() As Boolean ' /* ファイルがタイムアウトに対応しているかを返す */ ' Return False /*今のところ対応していないのでFalse*/ ' End Function*/ Override Function CanWrite() As Boolean /* ファイルが書き込みに対応しているかを返す */ If This.fileAccess And GENERIC_WRITE Then Return True Else Return False End If End Function /*Handle*/ Function IsAsync() As Boolean /* ファイルが非同期操作に対応しているかを返す */ If This.fileOptions=FILE_FLAG_OVERLAPPED/*FileOptions.Asynchronous*/ Then Return True Else Return False End If End Function Override Function Length() As Int64 If This.CanSeek() Then Dim length As LARGE_INTEGER length.LowPart=GetFileSize(This.handle,VarPtr(length.HighPart) As *DWord) Return MAKEQWORD(length.LowPart,length.HighPart) End If End Function Function Name() As String Return New String(This.filePath) End Function Override Sub Position(value As Int64) If This.CanSeek() Then If This.IsAsync() Then fileReadOverlapped.Offset=LODWORD(value) fileReadOverlapped.OffsetHigh=HIDWORD(value) fileWriteOverlapped.OffsetHigh=LODWORD(value) fileWriteOverlapped.OffsetHigh=HIDWORD(value) Else Dim position As LARGE_INTEGER position.LowPart=LODWORD(value) position.HighPart=HIDWORD(value) SetFilePointer(This.handle,position.LowPart,VarPtr(position.HighPart) As *DWord,FILE_BEGIN) End If End If End Sub Override Function Position() As Int64 If This.CanSeek() Then If This.IsAsync() Then Return MAKEQWORD(fileReadOverlapped.Offset,fileReadOverlapped.OffsetHigh) Else Dim position As LARGE_INTEGER ZeroMemory(VarPtr(position),SizeOf(LARGE_INTEGER)) position.LowPart=SetFilePointer(This.handle,position.LowPart,VarPtr(position.HighPart) As *DWord,FILE_CURRENT) Return MAKEQWORD(position.LowPart,position.HighPart) End If End If End Function /* Override Sub ReadTimeout(value As Long) 'TODO End Sub Override Function ReadTimeout() As Long 'TODO End Function*/ /* Safe〜Handle系の実装は要相談!! */ /* Function SafeFileHandle() As SafeFileHandle End Function*/ Override Sub WriteTimeout(value As Long) 'TODO End Sub Override Function WriteTimeout() As Long 'TODO End Function Public Override Function BeginRead(ByRef buffer[] As Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult If This.IsAsync() Then Else Read(buffer,offset,count) End If End Function Override Function BeginWrite(ByRef buffer[] As Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult If This.IsAsync() Then Else Write(buffer,offset,count) End If End Function Override Sub Close() CloseHandle(This.handle) End Sub /* CreateObjRef*/ /* Dispose*/ Override Sub EndRead(ByRef asyncResult As System.IAsyncResult) 'TODO End Sub Override Sub EndWrite(ByRef asyncResult As System.IAsyncResult) 'TODO End Sub /* Equals*/ Override Sub Flush() FlushFileBuffers(This.handle) End Sub /* Function GetAccessControl() As FileSecurity FileSecurityの実装がまだできてない。 End Function*/ Override Function GetHashCode() As Long Return ObjPtr(This) As Long End Function /* GetLifetimeService*/ /* Override Function GetType() As TypeInfo Return Super.GetType() End Function*/ /* InitializeLifetimeService*/ Sub Lock(position As Int64, length As Int64) End Sub Override Function Read( buffer As *Byte, offset As Long, count As Long) As Long If This.CanRead() Then Dim ret As DWord If This.IsAsync() Then ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),This.fileReadOverlapped) While This.fileReadOverlapped.Internal=STATUS_PENDING Wend fileReadOverlapped.Offset+=LODWORD(ret) fileReadOverlapped.OffsetHigh+=HIDWORD(ret) fileWriteOverlapped.Offset+=LODWORD(ret) fileWriteOverlapped.OffsetHigh+=HIDWORD(ret) Return ret Else ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),ByVal NULL) Return ret End If End If End Function /* ReferenceEquals*/ Override Function Seek(offset As Int64, origin As SeekOrigin) As Long If This.CanSeek() Then If This.IsAsync() Then Select Case origin Case SeekOrigin.Begin fileReadOverlapped.Offset=LODWORD(offset) fileReadOverlapped.OffsetHigh=HIDWORD(offset) fileWriteOverlapped.OffsetHigh=LODWORD(offset) fileWriteOverlapped.OffsetHigh=HIDWORD(offset) Case SeekOrigin.Current fileReadOverlapped.Offset+=LODWORD(offset) fileReadOverlapped.OffsetHigh+=HIDWORD(offset) fileWriteOverlapped.Offset+=LODWORD(offset) fileWriteOverlapped.OffsetHigh+=HIDWORD(offset) Case SeekOrigin.End fileReadOverlapped.Offset=LODWORD(This.Length()+offset) fileReadOverlapped.OffsetHigh=HIDWORD(This.Length()+offset) fileWriteOverlapped.Offset=LODWORD(This.Length()+offset) fileWriteOverlapped.OffsetHigh=HIDWORD(This.Length()+offset) End Select Else Dim seek As LARGE_INTEGER seek.LowPart=LODWORD(offset) seek.HighPart=HIDWORD(offset) If seek.HighPart=0 And offset<0 Then seek.LowPart=-seek.LowPart Select Case origin Case SeekOrigin.Begin Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_BEGIN) Case SeekOrigin.Current Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT) Case SeekOrigin.End Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT) End Select End If End If End Function /* Sub SetAccessControl(fileSecurity As FileSecurity) FileSecurityの実装がまだできてない。 End Sub*/ Override Sub SetLength(value As Int64) If This.CanWrite() and This.CanSeek() Then If This.IsAsync() Then Else Dim current = This.Position() This.Position(value) SetEndOfFile(This.handle) End If End If End Sub /* Synchronized*/ Override Function ToString() As String Return This.Name() End Function Sub Unlock(position As Int64, length As Int64) End Sub Override Sub Write(buffer As *Byte, offset As Long, count As Long) If This.CanWrite() Then Dim ret As DWord If This.IsAsync() Then WriteFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),This.fileWriteOverlapped) While This.fileReadOverlapped.Internal=STATUS_PENDING Wend This.fileReadOverlapped.Offset+=LODWORD(ret) This.fileReadOverlapped.OffsetHigh+=HIDWORD(ret) This.fileWriteOverlapped.Offset+=LODWORD(ret) This.fileWriteOverlapped.OffsetHigh+=HIDWORD(ret) Else WriteFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),ByVal NULL) End If End If End Sub Protected Override Function CreateWaitHandle() As System.Threading.WaitHandle '調査した限りでは、System.Threading.EventWaitHandleクラスをNewする模様。 '現状ではSystem.Threading.WaitHandleクラスをNewしてからHandleにて設定 Dim wh As System.Threading.WaitHandle wh.Handle=CreateEvent(NULL,TRUE,FALSE,NULL) Return wh End Function /* Dispose Finalize MemberwiseClone*/ Private End Class End Namespace End Namespace