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

Last change on this file since 349 was 349, checked in by NoWest, 17 years ago

せっかく修正していただいたEnd Function -> End Sub をまた元に戻してしまっていたので再度修正。

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(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(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 This.Dispose()
261 End Sub
262
263/* CreateObjRef*/
264
265 Override Sub Dispose()
266 CloseHandle(InterlockedExchangePointer(VarPtr(This.handle),NULL))
267 End Sub
268
269 Override Function EndRead(ByRef asyncResult As System.IAsyncResult) As Long
270 'TODO
271 End Function
272
273 Override Sub EndWrite(ByRef asyncResult As System.IAsyncResult)
274 'TODO
275 End Sub
276
277/* Equals*/
278
279 Override Sub Flush()
280 FlushFileBuffers(This.handle)
281 End Sub
282
283/* Function GetAccessControl() As FileSecurity
284 FileSecurityの実装がまだできてない。
285 End Function*/
286
287 Override Function GetHashCode() As Long
288 Return ObjPtr(This) As Long
289 End Function
290
291/* GetLifetimeService*/
292
293/* Override Function GetType() As TypeInfo
294 Return Super.GetType()
295 End Function*/
296
297/* InitializeLifetimeService*/
298
299 Sub Lock(position As Int64, length As Int64)
300 End Sub
301
302 Override Function Read( buffer As *Byte, offset As Long, count As Long) As Long
303 If This.CanRead() Then
304 Dim ret As DWord
305 If This.IsAsync() Then
306 ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),This.fileReadOverlapped)
307 While This.fileReadOverlapped.Internal=STATUS_PENDING
308 Wend
309 fileReadOverlapped.Offset+=LODWORD(ret)
310 fileReadOverlapped.OffsetHigh+=HIDWORD(ret)
311 fileWriteOverlapped.Offset+=LODWORD(ret)
312 fileWriteOverlapped.OffsetHigh+=HIDWORD(ret)
313 Return ret
314 Else
315 ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),ByVal NULL)
316 Return ret
317 End If
318 End If
319 End Function
320
321/* ReferenceEquals*/
322
323 Override Function Seek(offset As Int64, origin As SeekOrigin) As Long
324 If This.CanSeek() Then
325 If This.IsAsync() Then
326 Select Case origin
327 Case SeekOrigin.Begin
328 fileReadOverlapped.Offset=LODWORD(offset)
329 fileReadOverlapped.OffsetHigh=HIDWORD(offset)
330 fileWriteOverlapped.OffsetHigh=LODWORD(offset)
331 fileWriteOverlapped.OffsetHigh=HIDWORD(offset)
332 Case SeekOrigin.Current
333 fileReadOverlapped.Offset+=LODWORD(offset)
334 fileReadOverlapped.OffsetHigh+=HIDWORD(offset)
335 fileWriteOverlapped.Offset+=LODWORD(offset)
336 fileWriteOverlapped.OffsetHigh+=HIDWORD(offset)
337 Case SeekOrigin.End
338 fileReadOverlapped.Offset=LODWORD(This.Length()+offset)
339 fileReadOverlapped.OffsetHigh=HIDWORD(This.Length()+offset)
340 fileWriteOverlapped.Offset=LODWORD(This.Length()+offset)
341 fileWriteOverlapped.OffsetHigh=HIDWORD(This.Length()+offset)
342 End Select
343 Else
344 Dim seek As LARGE_INTEGER
345 seek.LowPart=LODWORD(offset)
346 seek.HighPart=HIDWORD(offset)
347 Select Case origin
348 Case SeekOrigin.Begin
349 Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_BEGIN)
350 Case SeekOrigin.Current
351 Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT)
352 Case SeekOrigin.End
353 Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT)
354 End Select
355 End If
356 End If
357 End Function
358
359/* Sub SetAccessControl(fileSecurity As FileSecurity)
360 FileSecurityの実装がまだできてない。
361 End Sub*/
362
363 Override Sub SetLength(value As Int64)
364 If This.CanWrite() and This.CanSeek() Then
365 If This.IsAsync() Then
366 Else
367 Dim current = This.Position()
368 This.Position(value)
369 SetEndOfFile(This.handle)
370 End If
371 End If
372 End Sub
373
374/* Synchronized*/
375
376 Override Function ToString() As String
377 Return This.Name()
378 End Function
379
380 Sub Unlock(position As Int64, length As Int64)
381 End Sub
382
383 Override Sub Write(buffer As *Byte, offset As Long, count As Long)
384 If This.CanWrite() Then
385 Dim ret As DWord
386 If This.IsAsync() Then
387 WriteFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),This.fileWriteOverlapped)
388 While This.fileReadOverlapped.Internal=STATUS_PENDING
389 Wend
390 This.fileReadOverlapped.Offset+=LODWORD(ret)
391 This.fileReadOverlapped.OffsetHigh+=HIDWORD(ret)
392 This.fileWriteOverlapped.Offset+=LODWORD(ret)
393 This.fileWriteOverlapped.OffsetHigh+=HIDWORD(ret)
394 Else
395 WriteFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),ByVal NULL)
396 End If
397 End If
398 End Sub
399
400
401Protected
402 Override Function CreateWaitHandle() As System.Threading.WaitHandle
403 '調査した限りでは、System.Threading.EventWaitHandleクラスをNewする模様。
404 '現状ではSystem.Threading.WaitHandleクラスをNewしてからHandleにて設定
405 Dim wh As System.Threading.WaitHandle
406 wh.Handle=CreateEvent(NULL,TRUE,FALSE,NULL)
407 Return wh
408 End Function
409
410/* Dispose
411 Finalize
412 MemberwiseClone*/
413Private
414End Class
415
416
417End Namespace
418End Namespace
Note: See TracBrowser for help on using the repository browser.