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

Last change on this file since 388 was 388, checked in by イグトランス (egtra), 16 years ago

Stringなどで例外を投げるようにした。
#147の解決。
CType ASCII文字判定関数群の追加。

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