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

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

非同期ファイル操作以外の実装はほぼ完了。
非同期は、インターフェイス、デリゲートの追加を待って実装予定。

File size: 11.4 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 Sub EndRead(ByRef asyncResult As System.IAsyncResult)
267 'TODO
268 End Sub
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(ByRef 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 Override Function ReadByte() As Long
319 Dim b As Byte
320 Dim ret = Read(b, 0, 1)
321 If ret <> 0 Then
322 Return b As Long
323 Else
324 Return -1
325 End If
326 End Function
327/* ReferenceEquals*/
328
329 Override Function Seek(offset As Int64, origin As SeekOrigin) As Long
330 If This.CanSeek() Then
331 If This.IsAsync() Then
332 Select Case origin
333 Case SeekOrigin.Begin
334 fileReadOverlapped.Offset=LODWORD(offset)
335 fileReadOverlapped.OffsetHigh=HIDWORD(offset)
336 fileWriteOverlapped.OffsetHigh=LODWORD(offset)
337 fileWriteOverlapped.OffsetHigh=HIDWORD(offset)
338 Case SeekOrigin.Current
339 fileReadOverlapped.Offset+=LODWORD(offset)
340 fileReadOverlapped.OffsetHigh+=HIDWORD(offset)
341 fileWriteOverlapped.Offset+=LODWORD(offset)
342 fileWriteOverlapped.OffsetHigh+=HIDWORD(offset)
343 Case SeekOrigin.End
344 fileReadOverlapped.Offset=LODWORD(This.Length()+offset)
345 fileReadOverlapped.OffsetHigh=HIDWORD(This.Length()+offset)
346 fileWriteOverlapped.Offset=LODWORD(This.Length()+offset)
347 fileWriteOverlapped.OffsetHigh=HIDWORD(This.Length()+offset)
348 End Select
349 Else
350 Dim seek As LARGE_INTEGER
351 seek.LowPart=LODWORD(offset)
352 seek.HighPart=HIDWORD(offset)
353 If seek.HighPart=0 And offset<0 Then seek.LowPart=-seek.LowPart
354 Select Case origin
355 Case SeekOrigin.Begin
356 Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_BEGIN)
357 Case SeekOrigin.Current
358 Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT)
359 Case SeekOrigin.End
360 Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT)
361 End Select
362 End If
363 End If
364 End Function
365
366/* Sub SetAccessControl(fileSecurity As FileSecurity)
367 FileSecurityの実装がまだできてない。
368 End Sub*/
369
370 Override Sub SetLength(value As Int64)
371 If This.CanWrite() and This.CanSeek() Then
372 If This.IsAsync() Then
373 Else
374 Dim current = This.Position()
375 This.Position(value)
376 SetEndOfFile(This.handle)
377 End If
378 End If
379 End Sub
380
381/* Synchronized*/
382
383 Override Function ToString() As String
384 Return This.Name()
385 End Function
386
387 Sub Unlock(position As Int64, length As Int64)
388 End Sub
389
390 Override Sub Write(ByRef buffer[] As Byte, offset As Long, count As Long)
391 If This.CanWrite() Then
392 Dim ret As DWord
393 If This.IsAsync() Then
394 WriteFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),This.fileWriteOverlapped)
395 While This.fileReadOverlapped.Internal=STATUS_PENDING
396 Wend
397 This.fileReadOverlapped.Offset+=LODWORD(ret)
398 This.fileReadOverlapped.OffsetHigh+=HIDWORD(ret)
399 This.fileWriteOverlapped.Offset+=LODWORD(ret)
400 This.fileWriteOverlapped.OffsetHigh+=HIDWORD(ret)
401 Else
402 WriteFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(ret),ByVal NULL)
403 End If
404 End If
405 End Sub
406
407 Override Sub WriteByte(b As Byte)
408 Write(b, 0, 1)
409 End Sub
410
411Protected
412 Override Function CreateWaitHandle() As System.Threading.WaitHandle
413 '調査した限りでは、System.Threading.EventWaitHandleクラスをNewする模様。
414 '現状ではSystem.Threading.WaitHandleクラスをNewしてからHandleにて設定
415 Dim wh As System.Threading.WaitHandle
416 wh.Handle=CreateEvent(NULL,TRUE,FALSE,NULL)
417 Return wh
418 End Function
419
420/* Dispose
421 Finalize
422 MemberwiseClone*/
423Private
424End Class
425
426
427End Namespace
428End Namespace
Note: See TracBrowser for help on using the repository browser.