source: trunk/Include/Classes/System/IO/FileStream.ab @ 339

Last change on this file since 339 was 339, checked in by dai, 16 years ago

FileStream?.EndReadメソッドのオーバーライドに失敗するミスを修正

File size: 11.1 KB
Line 
1Namespace System
2Namespace IO
3
4
5/* ほんとはmiscに入れるかかファイルを分けたほうがいいかもしれないが一先ず実装 */
6Enum FileOptions
7    Asynchronous
8    DeleteOnClose
9    Encrypted
10    None
11    RandomAccess
12    SequentialScan
13    WriteThrough
14End Enum
15
16Class FileStream
17    Inherits Stream
18
19    handle As HANDLE
20
21    /*
22    ファイルハンドルからこれらを取得できれば、これらは入らないが
23    今のところは不明なので自前で実装するしかない
24    */
25    filePath As String
26    fileMode As DWord
27    fileAccess As DWord
28    fileShare As DWord
29    fileOptions As DWord
30    fileReadOverlapped As OVERLAPPED
31    fileWriteOverlapped As OVERLAPPED
32
33Public
34    /* コンストラクタ.NETと同じように実装は難しい、一先ず動くものを実装したが変更が必要だと思う */
35    Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions)
36        Dim ac As DWord
37        Dim mo As DWord
38        Dim sh As DWord
39        Dim op As DWord
40
41        Select Case access
42            Case FileAccess.Read
43                ac=GENERIC_READ
44            Case FileAccess.ReadWrite
45                ac=GENERIC_READ or GENERIC_WRITE
46            Case FileAccess.Write
47                ac=GENERIC_WRITE
48        End Select
49
50        Select Case share
51            Case FileShare.DeleteFile
52                sh=FILE_SHARE_DELETE
53            Case FileShare.None
54                sh=0
55            Case FileShare.Read
56                sh=FILE_SHARE_READ
57            Case FileShare.ReadWrite
58                sh=FILE_SHARE_READ or FILE_SHARE_WRITE
59            Case FileShare.Write
60                sh=FILE_SHARE_WRITE
61        End Select
62
63        Select Case mode
64            Case FileMode.Append
65                mo=OPEN_ALWAYS
66            Case FileMode.Create
67                mo=CREATE_ALWAYS
68            Case FileMode.CreateNew
69                mo=CREATE_NEW
70            Case FileMode.Open
71                mo=OPEN_EXISTING
72            Case FileMode.OpenOrCreate
73                mo=OPEN_ALWAYS
74            Case FileMode.Truncate
75                mo=TRUNCATE_EXISTING
76        End Select
77
78        Select Case options
79            Case FileOptions.Asynchronous
80                op=FILE_FLAG_OVERLAPPED
81            Case FileOptions.DeleteOnClose
82                op=FILE_FLAG_DELETE_ON_CLOSE
83            Case FileOptions.Encrypted
84            Case FileOptions.None
85                op=0
86            Case FileOptions.RandomAccess
87                op=FILE_FLAG_RANDOM_ACCESS
88            Case FileOptions.SequentialScan
89                op=FILE_FLAG_SEQUENTIAL_SCAN
90            Case FileOptions.WriteThrough
91                op=FILE_FLAG_WRITE_THROUGH
92        End Select
93
94        This.handle=CreateFile(path As PSTR,ac,sh,ByVal NULL,mo,op,0)
95        If This.handle=INVALID_HANDLE_VALUE Then
96        'エラー処理
97        'Throw ArgumentException
98        'Throw IOException
99        'Throw System.IO.FileNotFoundException
100            This.handle=0
101            Beep(220,500)
102            Exit Sub
103        End If
104
105        This.filePath = path
106        This.fileMode = mo
107        This.fileAccess = ac
108        This.fileShare = sh
109        This.fileOptions = op
110    End Sub
111    Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare)
112        This.FileStream(path,mode,access,share,FileOptions.None)
113    End Sub
114    Sub FileStream(path As String, mode As FileMode, access As FileAccess)
115        This.FileStream(path,mode,access,FileShare.None,FileOptions.None)
116    End Sub
117    Sub FileStream(path As String, mode As FileMode)
118        Dim access As FileAccess
119        Select Case mode
120            Case FileMode.Append
121                access=FileAccess.Write
122            Case FileMode.Create
123                access=FileAccess.ReadWrite
124            Case FileMode.CreateNew
125                access=FileAccess.ReadWrite
126            Case FileMode.Open
127                access=FileAccess.ReadWrite
128            Case FileMode.OpenOrCreate
129                access=FileAccess.ReadWrite
130            Case FileMode.Truncate
131                access=FileAccess.Write
132        End Select
133        This.FileStream(path,mode,access,FileShare.None,FileOptions.None)
134    End Sub
135
136    Sub ~FileStream()
137        This.Flush()
138        This.Close()
139    End Sub
140
141Public
142    Override Function CanRead() As Boolean
143        /* ファイルが読み込みに対応しているかを返す */
144        If This.fileAccess And GENERIC_READ Then
145            Return True
146        Else
147            Return False
148        End If
149    End Function
150
151    Override Function CanSeek() As Boolean
152        /* ファイルがシークに対応しているかを返す */
153        If GetFileType(This.handle)=FILE_TYPE_DISK Then
154            Return True
155        Else
156            Return False
157        End If
158    End Function
159
160'   Override Function CanTimeout() As Boolean
161'       /* ファイルがタイムアウトに対応しているかを返す */
162'       Return False /*今のところ対応していないのでFalse*/
163'   End Function*/
164
165    Override Function CanWrite() As Boolean
166        /* ファイルが書き込みに対応しているかを返す */
167        If This.fileAccess And GENERIC_WRITE Then
168            Return True
169        Else
170            Return False
171        End If
172    End Function
173
174    /*Handle*/
175
176    Function IsAsync() As Boolean
177        /* ファイルが非同期操作に対応しているかを返す */
178        If This.fileOptions=FILE_FLAG_OVERLAPPED/*FileOptions.Asynchronous*/ Then
179            Return True
180        Else
181            Return False
182        End If
183    End Function
184
185    Override Function Length() As Int64
186        If This.CanSeek() Then
187            Dim length As LARGE_INTEGER
188            length.LowPart=GetFileSize(This.handle,VarPtr(length.HighPart) As *DWord)
189            Return MAKEQWORD(length.LowPart,length.HighPart)
190        End If
191    End Function
192
193    Function Name() As String
194        Return New String(This.filePath)
195    End Function
196   
197    Override Sub Position(value As Int64)
198        If This.CanSeek() Then
199            If This.IsAsync() Then
200                fileReadOverlapped.Offset=LODWORD(value)
201                fileReadOverlapped.OffsetHigh=HIDWORD(value)
202                fileWriteOverlapped.OffsetHigh=LODWORD(value)
203                fileWriteOverlapped.OffsetHigh=HIDWORD(value)
204            Else
205                Dim position As LARGE_INTEGER
206                position.LowPart=LODWORD(value)
207                position.HighPart=HIDWORD(value)
208                SetFilePointer(This.handle,position.LowPart,VarPtr(position.HighPart) As *DWord,FILE_BEGIN)
209            End If
210        End If
211    End Sub
212    Override Function Position() As Int64
213        If This.CanSeek() Then
214            If This.IsAsync() Then
215                Return MAKEQWORD(fileReadOverlapped.Offset,fileReadOverlapped.OffsetHigh)
216            Else
217                Dim position As LARGE_INTEGER
218                ZeroMemory(VarPtr(position),SizeOf(LARGE_INTEGER))
219                position.LowPart=SetFilePointer(This.handle,position.LowPart,VarPtr(position.HighPart) As *DWord,FILE_CURRENT)
220                Return MAKEQWORD(position.LowPart,position.HighPart)
221            End If
222        End If
223    End Function
224
225/*  Override Sub ReadTimeout(value As Long)
226        'TODO
227    End Sub
228    Override Function ReadTimeout() As Long
229        'TODO
230    End Function*/
231
232    /* Safe~Handle系の実装は要相談!! */
233/*  Function SafeFileHandle() As SafeFileHandle
234    End Function*/
235
236    Override Sub WriteTimeout(value As Long)
237        'TODO
238    End Sub
239    Override Function WriteTimeout() As Long
240        'TODO
241    End Function
242   
243
244Public
245    Override Function BeginRead(ByRef buffer[] As Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult
246        If This.IsAsync() Then
247        Else
248            Read(buffer,offset,count)
249        End If
250    End Function
251
252    Override Function BeginWrite(ByRef buffer[] As Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult
253        If This.IsAsync() Then
254        Else
255            Write(buffer,offset,count)
256        End If
257    End Function
258
259    Override Sub Close()
260        CloseHandle(This.handle)
261    End Sub
262
263/*  CreateObjRef*/
264/*  Dispose*/
265
266    Override Function EndRead(ByRef asyncResult As System.IAsyncResult) As Long
267        'TODO
268    End Function
269
270    Override Sub EndWrite(ByRef asyncResult As System.IAsyncResult)
271        'TODO
272    End Sub
273
274/*  Equals*/
275
276    Override Sub Flush()
277        FlushFileBuffers(This.handle)
278    End Sub
279
280/*  Function GetAccessControl() As FileSecurity
281    FileSecurityの実装がまだできてない。
282    End Function*/
283
284    Override Function GetHashCode() As Long
285        Return ObjPtr(This) As Long
286    End Function
287
288/*  GetLifetimeService*/
289
290/*  Override Function GetType() As TypeInfo
291        Return Super.GetType()
292    End Function*/
293
294/*  InitializeLifetimeService*/
295
296    Sub Lock(position As Int64, length As Int64)
297    End Sub
298
299    Override Function Read( buffer As *Byte, offset As Long, count As Long) As Long
300        If This.CanRead() Then
301            Dim ret As DWord
302            If This.IsAsync() Then
303                ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),This.fileReadOverlapped)
304                While This.fileReadOverlapped.Internal=STATUS_PENDING
305                Wend
306                fileReadOverlapped.Offset+=LODWORD(ret)
307                fileReadOverlapped.OffsetHigh+=HIDWORD(ret)
308                fileWriteOverlapped.Offset+=LODWORD(ret)
309                fileWriteOverlapped.OffsetHigh+=HIDWORD(ret)
310                Return ret
311            Else
312                ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),ByVal NULL)
313                Return ret
314            End If
315        End If
316    End Function
317
318/*  ReferenceEquals*/
319
320    Override Function Seek(offset As Int64, origin As SeekOrigin) As Long
321        If This.CanSeek() Then
322            If This.IsAsync() Then
323                Select Case origin
324                    Case SeekOrigin.Begin
325                        fileReadOverlapped.Offset=LODWORD(offset)
326                        fileReadOverlapped.OffsetHigh=HIDWORD(offset)
327                        fileWriteOverlapped.OffsetHigh=LODWORD(offset)
328                        fileWriteOverlapped.OffsetHigh=HIDWORD(offset)
329                    Case SeekOrigin.Current
330                        fileReadOverlapped.Offset+=LODWORD(offset)
331                        fileReadOverlapped.OffsetHigh+=HIDWORD(offset)
332                        fileWriteOverlapped.Offset+=LODWORD(offset)
333                        fileWriteOverlapped.OffsetHigh+=HIDWORD(offset)
334                    Case SeekOrigin.End
335                        fileReadOverlapped.Offset=LODWORD(This.Length()+offset)
336                        fileReadOverlapped.OffsetHigh=HIDWORD(This.Length()+offset)
337                        fileWriteOverlapped.Offset=LODWORD(This.Length()+offset)
338                        fileWriteOverlapped.OffsetHigh=HIDWORD(This.Length()+offset)
339                End Select
340            Else
341                Dim seek As LARGE_INTEGER
342                seek.LowPart=LODWORD(offset)
343                seek.HighPart=HIDWORD(offset)
344                If seek.HighPart=0 And offset<0 Then seek.LowPart=-seek.LowPart
345                Select Case origin
346                    Case SeekOrigin.Begin
347                        Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_BEGIN)
348                    Case SeekOrigin.Current
349                        Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT)
350                    Case SeekOrigin.End
351                        Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT)
352                End Select
353            End If
354        End If
355    End Function
356
357/*  Sub SetAccessControl(fileSecurity As FileSecurity)
358    FileSecurityの実装がまだできてない。
359    End Sub*/
360
361    Override Sub SetLength(value As Int64)
362        If This.CanWrite() and This.CanSeek() Then
363            If This.IsAsync() Then
364            Else
365                Dim current = This.Position()
366                This.Position(value)
367                SetEndOfFile(This.handle)
368            End If
369        End If
370    End Sub
371
372/*  Synchronized*/
373
374    Override Function ToString() As String
375        Return This.Name()
376    End Function
377
378    Sub Unlock(position As Int64, length As Int64)
379    End Sub
380
381    Override Sub Write(buffer As *Byte, offset As Long, count As Long)
382        If This.CanWrite() Then
383            Dim ret As DWord
384            If This.IsAsync() Then
385                WriteFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),This.fileWriteOverlapped)
386                While This.fileReadOverlapped.Internal=STATUS_PENDING
387                Wend
388                This.fileReadOverlapped.Offset+=LODWORD(ret)
389                This.fileReadOverlapped.OffsetHigh+=HIDWORD(ret)
390                This.fileWriteOverlapped.Offset+=LODWORD(ret)
391                This.fileWriteOverlapped.OffsetHigh+=HIDWORD(ret)
392            Else
393                WriteFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),ByVal NULL)
394            End If
395        End If
396    End Sub
397
398Protected
399    Override Function CreateWaitHandle() As System.Threading.WaitHandle
400        '調査した限りでは、System.Threading.EventWaitHandleクラスをNewする模様。
401        '現状ではSystem.Threading.WaitHandleクラスをNewしてからHandleにて設定
402        Dim wh As System.Threading.WaitHandle
403        wh.Handle=CreateEvent(NULL,TRUE,FALSE,NULL)
404        Return wh
405    End Function
406
407/*  Dispose
408    Finalize
409    MemberwiseClone*/
410Private
411End Class
412
413
414End Namespace
415End Namespace
Note: See TracBrowser for help on using the repository browser.