Ignore:
Timestamp:
Dec 7, 2007, 12:21:58 AM (17 years ago)
Author:
イグトランス (egtra)
Message:

FileStream非同期読み書きの修正、例外処理の追加。

Location:
trunk/Include/Classes/System/IO
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Include/Classes/System/IO/FileStream.ab

    r388 r391  
    44/* ほんとはmiscに入れるかかファイルを分けたほうがいいかもしれないが一先ず実装 */
    55Enum FileOptions
    6     Asynchronous
    7     DeleteOnClose
    8     Encrypted
    9     None
    10     RandomAccess
    11     SequentialScan
    12     WriteThrough
     6    None = 0
     7    Asynchronous = FILE_FLAG_OVERLAPPED
     8    DeleteOnClose = FILE_FLAG_DELETE_ON_CLOSE
     9    Encrypted = FILE_ATTRIBUTE_ENCRYPTED
     10    RandomAccess = FILE_FLAG_RANDOM_ACCESS
     11    SequentialScan = FILE_FLAG_SEQUENTIAL_SCAN
     12    WriteThrough = FILE_FLAG_WRITE_THROUGH
    1313End Enum
    1414
     
    7575        End Select
    7676
    77         Select Case options
    78             Case FileOptions.Asynchronous
    79                 op=FILE_FLAG_OVERLAPPED
    80             Case FileOptions.DeleteOnClose
    81                 op=FILE_FLAG_DELETE_ON_CLOSE
    82             Case FileOptions.Encrypted
    83             Case FileOptions.None
    84                 op=0
    85             Case FileOptions.RandomAccess
    86                 op=FILE_FLAG_RANDOM_ACCESS
    87             Case FileOptions.SequentialScan
    88                 op=FILE_FLAG_SEQUENTIAL_SCAN
    89             Case FileOptions.WriteThrough
    90                 op=FILE_FLAG_WRITE_THROUGH
    91         End Select
    92 
    93         This.handle=CreateFile(path As PSTR,ac,sh,ByVal NULL,mo,op,0)
     77        op = options As DWord
     78        If Not Environment.OSVersion.Platform = PlatformID.Win32NT Then
     79            op And= Not FILE_FLAG_OVERLAPPED
     80        End If
     81
     82        This.handle=CreateFile(ToTCStr(path),ac,sh,ByVal NULL,mo,op,0)
    9483        If This.handle=INVALID_HANDLE_VALUE Then
    9584        'エラー処理
     
    134123    End Sub
    135124Public
     125    /*!
     126    @brief  ファイルが読み込みに対応しているかを返す
     127    */
    136128    Override Function CanRead() As Boolean
    137         /* ファイルが読み込みに対応しているかを返す */
    138129        If This.fileAccess And GENERIC_READ Then
    139130            Return True
     
    143134    End Function
    144135
     136    /*!
     137    @brief  ファイルがシークに対応しているかを返す
     138    */
    145139    Override Function CanSeek() As Boolean
    146         /* ファイルがシークに対応しているかを返す */
    147140        If GetFileType(This.handle)=FILE_TYPE_DISK Then
    148141            Return True
     
    157150'   End Function*/
    158151
     152    /*!
     153    @brief  ファイルが書き込みに対応しているかを返す
     154    */
    159155    Override Function CanWrite() As Boolean
    160         /* ファイルが書き込みに対応しているかを返す */
    161156        If This.fileAccess And GENERIC_WRITE Then
    162157            Return True
     
    168163    /*Handle*/
    169164
     165    /*!
     166    @brief  ファイルが非同期操作に対応しているかを返す
     167    */
    170168    Function IsAsync() As Boolean
    171         /* ファイルが非同期操作に対応しているかを返す */
    172169        If This.fileOptions And FILE_FLAG_OVERLAPPED /*FileOptions.Asynchronous*/ Then
    173170            Return True
     
    178175
    179176    Override Function Length() As Int64
     177        disposedCheck()
    180178        If This.CanSeek() Then
    181             Dim length As LARGE_INTEGER
    182             length.LowPart=GetFileSize(This.handle,VarPtr(length.HighPart) As *DWord)
    183             Return MAKEQWORD(length.LowPart,length.HighPart) As Int64
     179            Dim length = VarPtr(Length) As *ULARGE_INTEGER
     180            length->LowPart = GetFileSize(This.handle, VarPtr(length->HighPart))
     181            If LODWORD(Length) = INVALID_FILE_SIZE Then
     182                Dim error = GetLastError()
     183                If error <> NO_ERROR Then
     184'                   Detail.ThrowWinIOException("FileStream.Read: Failed to read.", error)
     185                End If
     186            End If
     187           
     188            If Length < 0 Then
     189                Debug 'Throw OverflowException
     190            End If
    184191        End If
    185192    End Function
     
    190197   
    191198    Override Sub Position(value As Int64)
     199        disposedCheck()
    192200        If This.CanSeek() Then
    193201            If This.IsAsync() Then
     
    202210    End Sub
    203211    Override Function Position() As Int64
     212        disposedCheck()
    204213        If This.CanSeek() Then
    205214            If This.IsAsync() Then
     
    266275
    267276    Override Sub Flush()
    268         FlushFileBuffers(This.handle)
     277        disposedCheck()
     278        Dim ret = FlushFileBuffers(This.handle)
     279        If ret = FALSE Then
     280'           Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
     281        End If
    269282    End Sub
    270283
     
    273286    End Function*/
    274287
    275     Override Function GetHashCode() As Long
    276         Return ObjPtr(This) As Long
    277     End Function
    278 
    279288/*  GetLifetimeService*/
    280289
     
    286295
    287296    Sub Lock(position As Int64, length As Int64)
     297        disposedCheck()
    288298        If position < 0 Then
    289299            Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(position), "position")
     
    296306
    297307    Override Function Read( buffer As *Byte, offset As Long, count As Long) As Long
    298         If This.CanRead() Then
    299             Dim readBytes As DWord
    300             If This.IsAsync() Then
    301                 Dim overlapped As OVERLAPPED
    302                 SetQWord(VarPtr(overlapped.Offset), offset)
    303                 Dim ret = ReadFile(This.handle, VarPtr(buffer[offset]), count, 0, overlapped)
     308        disposedCheck()
     309        If buffer = 0 Then
     310'           Throw ArgumentNullException("FileStream.Read: An argument is null value.", "buffer")
     311        ElseIf Not This.CanRead() Then
     312'           Throw NotSupportedException("FileStream.Read: This stream is not readable.")
     313        End If
     314
     315        Dim ret As BOOL
     316        Dim readBytes As DWord
     317        If This.IsAsync() Then
     318            Dim overlapped As OVERLAPPED
     319            SetQWord(VarPtr(overlapped.Offset), offset)
     320            overlapped.hEvent = CreateEvent(0, TRUE, FALSE, 0)
     321            If overlapped.hEvent = 0 Then
     322'               Throw OutOfMemoryException("FileStream.Read: Failed to create an event object.")
     323            End If
     324            Try
     325                ret = ReadFile(This.handle, VarPtr(buffer[offset]), count, 0, overlapped)
    304326                If ret = FALSE Then
    305                     If GetLastError() = ERROR_IO_PENDING Then
    306                         GetOverlappedResult(This.handle, overlapped, readBytes, TRUE)
     327                    Dim error = GetLastError()
     328                    If error <> ERROR_IO_PENDING Then
     329'                       Detail.ThrowWinIOException("FileStream.Read: Failed to read.", error)
    307330                    End If
    308331                End If
     332                ret = GetOverlappedResult(This.handle, overlapped, readBytes, TRUE)
     333                If ret = FALSE Then
     334'                   Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
     335                End If
    309336                offset += Read
    310             Else
    311                 ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(readBytes),ByVal NULL)
    312             End If
    313             Read = readBytes As Long
    314         End If
    315     End Function
    316 
    317 /*  ReferenceEquals*/
    318 
    319     Override Function Seek(offset As Int64, origin As SeekOrigin) As Long
     337            Finally
     338                CloseHandle(overlapped.hEvent)
     339            End Try
     340        Else
     341            ret = ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(readBytes),ByVal NULL)
     342            If ret = FALSE Then
     343'               Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
     344            End If
     345        End If
     346        Read = readBytes As Long
     347    End Function
     348
     349    /*!
     350    @brief  ストリームの現在位置を移動させる。
     351    @param[in] offset   originからの移動量
     352    @param[in] origin   移動の基準位置
     353    @return 移動後の新しい現在位置
     354    @exception DisposedException    既にストリームが閉じられている場合
     355    @exception ArgumentException    移動後の位置が負の位置(ファイル先頭より手前)になる場合
     356    @exception IOException  その他エラーが発生した場合
     357    */
     358    Override Function Seek(offset As Int64, origin As SeekOrigin) As Int64
     359        disposedCheck()
    320360        If This.CanSeek() Then
    321361            If This.IsAsync() Then
     
    328368                        This.offset = This.Length + offset
    329369                End Select
     370                Seek = This.offset As Int64
     371                If Seek < 0 Then
     372'                   Throw ArgumentException("FileStream.Seek: Cannot seek to negative offset.")
     373                End If
    330374            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
     375                Dim seek = VarPtr(offset) As *ULARGE_INTEGER
     376                Dim ret = SetFilePointer(This.handle, seek->LowPart, VarPtr(seek->HighPart), origin As DWord)
     377                If ret = INVALID_SET_FILE_POINTER Then
     378                    Dim error = GetLastError()
     379                    If error = ERROR_NEGATIVE_SEEK Then
     380'                       Throw ArgumentException("FileStream.Seek: Cannot seek to negative offset.")
     381                    ElseIf error <> NO_ERROR Then
     382'                       Throw Detail.ThrowWinIOException("FileStream.Seek: Failed to seek.", error)
     383                    End If
     384                End If
     385                seek->LowPart = ret
     386                Seek = offset
    342387            End If
    343388        End If
     
    349394
    350395    Override Sub SetLength(value As Int64)
     396        disposedCheck()
    351397        If This.CanWrite() and This.CanSeek() Then
    352398            If This.IsAsync() Then
     
    354400                Dim current = This.Position()
    355401                This.Position(value)
    356                 SetEndOfFile(This.handle)
     402                Dim ret = SetEndOfFile(This.handle)
     403                If ret = FALSE Then
     404                    Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
     405                End If
     406                Position = current
    357407            End If
    358408        End If
     
    366416
    367417    Sub Unlock(position As Int64, length As Int64)
     418        disposedCheck()
    368419        If position < 0 Then
    369420            Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(position), "position")
     
    371422            Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(length), "length")
    372423        End If
    373         UnlockFile(handle, LODWORD(position As QWord), HIDWORD(position As QWord),
     424        Dim ret = UnlockFile(handle, LODWORD(position As QWord), HIDWORD(position As QWord),
    374425            LODWORD(length As QWord), HIDWORD(length As QWord))
    375     End Sub
    376 
     426        If ret = FALSE Then
     427            Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
     428        End If
     429    End Sub
    377430
    378431    Override Sub Write(buffer As *Byte, offset As Long, count As Long)
     432        disposedCheck()
    379433        If This.CanWrite() Then
    380434            Dim writeBytes As DWord
     
    382436                Dim overlapped As OVERLAPPED
    383437                SetQWord(VarPtr(overlapped.Offset), offset)
     438                overlapped.hEvent = CreateEvent(0, TRUE, FALSE, 0)
    384439                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
     440                If ret <> FALSE Or GetLastError() = ERROR_IO_PENDING Then
     441                    GetOverlappedResult(This.handle, overlapped, writeBytes, TRUE)
    389442                End If
    390443                offset += writeBytes
     444                CloseHandle(overlapped.hEvent)
    391445            Else
    392446                WriteFile(This.handle, VarPtr(buffer[offset]), count, VarPtr(writeBytes), ByVal NULL)
     
    394448        End If
    395449    End Sub
    396 
    397450
    398451Protected
     
    405458    End Function
    406459
    407 /*  Dispose
    408     Finalize
    409     MemberwiseClone*/
    410460Private
     461    Sub disposedCheck()
     462        If handle = 0 Then
     463'           Throw ObjectDisposedException("FileStream: This stream has closed.")
     464        End If
     465    End Sub
     466
    411467End Class
    412468
  • trunk/Include/Classes/System/IO/Stream.ab

    r388 r391  
    7070    End Function
    7171
    72     Abstract Function Seek(offset As Int64, origin As SeekOrigin) As Long
     72    Abstract Function Seek(offset As Int64, origin As SeekOrigin) As Int64
    7373    Abstract Sub SetLength(value As Int64)
    7474    Abstract Sub Write(buffer As *Byte, offset As Long, count As Long)
  • trunk/Include/Classes/System/IO/misc.ab

    r318 r391  
    11
    2 TypeDef /* [Delegate] */ AsyncCallback = *Sub(ByRef ar As System.IAsyncResult)
     2Namespace System
     3Namespace IO
    34
    45Enum SeekOrigin
    5     Begin
    6     Current
    7     End
     6    Begin = FILE_BEGIN
     7    Current = FILE_CURRENT
     8    End = FILE_END
    89End Enum
    910
     
    1213    TopDirectoryOnly
    1314End Enum
     15
     16End Namespace 'IO
     17End Namespace 'System
Note: See TracChangeset for help on using the changeset viewer.