VB 二進位塊讀寫類別模組(第一版)

來源:互聯網
上載者:User

'CFileRead.cls-----------------------------------------------------------------------------------

Option Explicit

'***************************************************************
'讀寫檔案的類,為檔案的讀寫操作提供了封裝,用起來更方便,重用度好
'這是讀檔案的類。
'。2005-3-7 Last modified.
'***************************************************************

Private m_bFileOpened As Boolean '檔案開啟標誌

Private m_iFileNum As Integer '檔案號,為什麼用Integer,由FreeFile的定義得知

Private m_lFileLen As Long '檔案長度

Private Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, _
Source As Any, ByVal Length As Long)

Public Function OpenBinary(ByVal sFQFilename As String) As Boolean
'開啟一個二進位檔案,成功返回真,失敗返回假
'INPUT------------------------------------------------------------
'sFQFilename        要開啟檔案的全路徑名
'-----------------------------------------------------------------
'OUTPUT-----------------------------------------------------------
'傳回值             成功返回真,失敗返回假
'-----------------------------------------------------------------
'備忘-------------------------------------------------------------
'該類的一個執行個體在同一時間只能夠開啟一個檔案。
'-----------------------------------------------------------------

OpenBinary = False 'default Return value.

On Error GoTo catch '錯誤捕獲

If m_bFileOpened Then Err.Raise 1000 '如果該類的執行個體正處在開啟檔案的
'狀態,那麼不允許開啟另一個檔案,引發一個錯誤。這意味著這個類遵循強嚴謹
'性編碼規則,而非強容錯性編碼規則(按這個規則的要求,就不會報錯,而是自
'動關閉上一個開啟的檔案)

m_iFileNum = FreeFile '取得一個合法檔案號

'以二進位、唯讀方式開啟檔案
Open sFQFilename For Binary Access Read As #m_iFileNum

m_bFileOpened = True '如果能執行到這一句,說明檔案開啟了,選項組

m_lFileLen = LOF(m_iFileNum) '取得檔案長度

OpenBinary = True 'return succeed flag!!!

Exit Function
catch:
End Function

Public Sub CloseFile()
'關閉曾經用OpenBinary開啟過的檔案

If m_bFileOpened Then '如果現在正處在開啟檔案的狀態。

    '如果目前狀態為有檔案開啟,那麼關閉它,並設定目前狀態
    Close #m_iFileNum '關閉檔案
    m_bFileOpened = False '檔案開啟標誌設為假
    m_iFileNum = -1 '把檔案號和檔案長度設為無效值
    m_lFileLen = -1
Else
    '如果沒有開啟檔案
    Err.Raise 1000 '報錯,這意味著這個類遵循強嚴謹
'性編碼規則
End If

End Sub

'幾個唯讀屬性------------------------------------------
Public Property Get FileNumber() As Integer
FileNumber = m_iFileNum
End Property

Public Property Get FileOpened() As Boolean
FileOpened = m_bFileOpened
End Property

Public Property Get FileLength() As Long
FileLength = m_lFileLen
End Property
'-------------------------------------------------------

Public Function ReadBlock(ByVal lpBuffer As Long, _
ByVal lBufferSize As Long) As Long
'讀檔案的塊,在使用此方法前需要先開啟檔案
'INPUT------------------------------------------------------------------------------
'lpBuffer         用來接受資料的緩衝區指標
'lBufferSize      指出緩衝區的大小(以位元組計)
'                (也就是期望從檔案中讀取的位元組數)
'OUTPUT-----------------------------------------------------------------------------
'傳回值           實際讀取到緩衝區的位元組數,可能等於也可能小於 lBufferSize

Dim lTemp As Long
Dim aBuf() As Byte

'計算出從當前檔案指標開始到檔案末尾還有多少位元組未讀
'計算方法就是檔案長度減去已讀的位元組數,就是未讀的位元組數
'就是 m_lFileLen-(seek(m_ifilenum)-1)
lTemp = m_lFileLen - Seek(m_iFileNum) + 1

If lTemp >= lBufferSize Then '[lBufferSize..)
'未讀位元組數大於等於緩衝區大小

    '可以填滿緩衝區(這種情況的出現機率較大,所以放在最前)
    ReadBlock = lBufferSize '返回實際讀取到緩衝區的位元組數
    ReDim aBuf(0 To lBufferSize - 1) '分配空間,大小是lBufferSize
    Get #m_iFileNum, , aBuf() '從檔案中讀取 lBufferSize個位元組
    CopyMemory ByVal lpBuffer, aBuf(0), lBufferSize
    '把資料複製到客戶的緩衝區
   
ElseIf lTemp > 0 Then '(0..lBufferSize) 也即 [1..lBufferSize-1]
    ' 0< lTemp < lBufferSize

    '還有位元組需要讀,但不足以填滿緩衝區
    ReadBlock = lTemp '返回實際讀取的位元組數
    ReDim aBuf(0 To lTemp - 1) '定義一個剛好能容納將要讀取資料的數組
    Get #m_iFileNum, , aBuf() '讀塊
    CopyMemory ByVal lpBuffer, aBuf(0), lTemp '投放到客戶提供的緩衝區裡

Else '( ..0]
   
     '沒有位元組需要讀了,回吧
    ReadBlock = 0 '返回實際讀取到緩衝區的位元組數
   
End If
   
End Function

Private Sub Class_Terminate()
If m_bFileOpened Then Err.Raise 1000, , "Please Close File"
End Sub
'---------------------------------------------------------------------------------------------------------------------------

'CFileWrite.cls--------------------------------------------------------------------------------------------------------

Option Explicit

'***************************************************************
'讀寫檔案的類,為檔案的讀寫操作提供了封裝,用起來更方便,重用度好
'這是寫檔案的類。
'。2005-3-7 Last modified.
'***************************************************************

'CFileWrite--------------------------------------------------------------------------

Private m_bFileOpened As Boolean '檔案開啟標誌

Private m_iFileNum As Integer '檔案號,為什麼用Integer,由FreeFile的定義得知

Private m_lFileLen As Long '檔案長度

Private Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, Source As Any, _
ByVal Length As Long)

Public Function OpenBinary(ByVal sFQFilename As String) As Boolean
'開啟一個檔案,成功返回真,失敗返回假
'INPUT------------------------------------------------------------
'sFQFilename        要開啟檔案的全路徑名
'-----------------------------------------------------------------
'OUTPUT-----------------------------------------------------------
'傳回值             成功返回真,失敗返回假
'-----------------------------------------------------------------
'備忘-------------------------------------------------------------
'該類的一個執行個體在同一時間只能夠開啟一個檔案。
'-----------------------------------------------------------------

OpenBinary = False 'default Return

On Error GoTo catch

If m_bFileOpened Then Err.Raise 1000 '如果該類的執行個體正處在開啟檔案的
'狀態,那麼不允許開啟另一個檔案,引發一個錯誤。這意味著這個類遵循強嚴謹
'性編碼規則,而非強容錯性編碼規則(按這個規則的要求,就不會報錯,而是自
'動關閉上一個開啟的檔案)

m_iFileNum = FreeFile '取得一個合法檔案號

'以二進位、唯寫方式開啟檔案
Open sFQFilename For Binary Access Write As #m_iFileNum

m_bFileOpened = True '如果能執行到這一句,說明檔案開啟了,選項組

m_lFileLen = LOF(m_iFileNum) '取得檔案長度

OpenBinary = True 'return succeed flag!!!
Exit Function
catch:
End Function

Public Sub CloseFile()
'關閉曾經用OpenBinary開啟過的檔案

If m_bFileOpened Then '如果現在正處在開啟檔案的狀態。

    '如果目前狀態為有檔案開啟,那麼關閉它,並設定目前狀態
    Close #m_iFileNum '關閉檔案
    m_bFileOpened = False '檔案開啟標誌設為假
    m_iFileNum = -1 '把檔案號和檔案長度設為無效值
    m_lFileLen = -1
Else
    '如果沒有開啟檔案
    Err.Raise 1000 '報錯,這意味著這個類遵循強嚴謹
'性編碼規則
End If

End Sub

'唯讀屬性------------------------------------------
Public Property Get FileNumber() As Integer
FileNumber = m_iFileNum
End Property

Public Property Get FileOpened() As Boolean
FileOpened = m_bFileOpened
End Property

Public Property Get FileLength() As Long
FileLength = m_lFileLen
End Property
'-------------------------------------------------------

Public Sub WriteBlock(ByVal lpBuffer As Long, ByVal nCount As Long)
'把一塊緩衝區的資料寫入到檔案中,前提是檔案必須開啟
'INPUT--------------------------------------------------------------
'lpBuffer     資料緩衝區的指標
'nCount       期望寫入的位元組數
'OUTPUT-------------------------------------------------------------
'N/A
'
Dim aBuf() As Byte

If nCount <= 0 Then Exit Sub

ReDim aBuf(0 To nCount - 1) '定義一個於期望寫入的位元組數大小相等的數組

CopyMemory aBuf(0), ByVal lpBuffer, nCount '把客戶提供的資料拷貝到aBuf()中

Put #m_iFileNum, , aBuf() '寫到檔案

End Sub

Private Sub Class_Terminate()
If m_bFileOpened Then Err.Raise 1000, , "Please Close File"
End Sub

'----------------------------------------------------------------------------------------------------------------------------

'以下是使用範例-------------------------------------------------------------------------------------------------------

VB 二進位塊讀寫類別模組應用執行個體,包括一個檔案拷貝和一個檔案二進位比較的例子。

'form1.frm--------------------------------------------------------------------------------------------------------------

 檔案拷貝執行個體:(Text1存放源檔案位置,Text2存放目標檔案位置)------------------------------------------------------------------------

Private Sub Command3_Click()
Const BUFFER_SIZE = 40960 * 2 '規定緩衝區大小
Dim nActual As Long
Dim aBuf(0 To BUFFER_SIZE - 1) As Byte '分配緩衝區
Dim tmr As Single '計時變數
Dim lFileLen As Long '紀錄檔案長度
Dim iFileNum As Integer '記錄檔案號
Dim k As Long

tmr = Timer

If Not m_cFileRead.OpenBinary(Text1.Text) Then MsgBox "開啟檔案失敗!" & Text1.Text
If Not m_cFileWrite.OpenBinary(Text2.Text) Then MsgBox "開啟檔案失敗!" & Text2.Text

'記下檔案長度和開啟檔案所用的檔案號,是為了最佳化效能。
lFileLen = m_cFileRead.FileLength
iFileNum = m_cFileRead.FileNumber

k = 0
Do
    k = k + 1
    If k = 10 Then
        k = 0
        'pb1是進度條控制項。
        pb1.Value = 100 * (Seek(iFileNum) / lFileLen) '顯示百分比
        DoEvents
    End If
    '讀塊,傳給它緩衝區指標和期望讀取的位元組數,返回實際讀取的位元組數,
    nActual = m_cFileRead.ReadBlock(VarPtr(aBuf(0)), BUFFER_SIZE)
    '寫塊,傳給它緩衝區指標和期望寫入的位元組數。
    m_cFileWrite.WriteBlock VarPtr(aBuf(0)), nActual
Loop Until nActual < BUFFER_SIZE '當實際讀取位元組數小於緩衝區大小的時候,就不需要再讀啦,已讀完啦

m_cFileRead.CloseFile '關檔案
m_cFileWrite.CloseFile

MsgBox "OK! total time:" & Timer - tmr
End Sub

---------------------------------------------------------------------------------------------------------------------------------------

二進位檔案比較執行個體(Text1存放第一個檔案的位置,Text2存放第二個檔案的位置)----------------------------

Private Sub Command2_Click()

Const BUFFER_SIZE As Long = 4096 * 2 '規定緩衝區大小
Dim cfRead1 As New CFileRead
Dim cfread2 As New CFileRead
Dim aBuf1(0 To BUFFER_SIZE - 1) As Byte '分配緩衝區
Dim aBuf2(0 To BUFFER_SIZE - 1) As Byte
Dim nActual  As Long
Dim i As Long, lCurPos As Long
Dim tmr As Single
Dim k As Long

tmr = Timer

If Not cfRead1.OpenBinary(Text1.Text) Then MsgBox "open file failed:" & Text1.Text
If Not cfread2.OpenBinary(Text2.Text) Then MsgBox "open file failed:" & Text2.Text

If cfRead1.FileLength <> cfread2.FileLength Then MsgBox "檔案不一樣長"

lCurPos = 1 '當前待比較位元組的位置,虛擬位置,不同於檔案的讀寫指標。
k = 0
Do
    '讀塊,傳給它緩衝區指標和期望讀取的位元組數,返回實際讀取的位元組數,
    nActual = cfRead1.ReadBlock(VarPtr(aBuf1(0)), BUFFER_SIZE)
    '讀第2個檔案的資料區塊
    nActual = cfread2.ReadBlock(VarPtr(aBuf2(0)), BUFFER_SIZE)
   
    For i = 0 To nActual - 1 '比較緩衝區
        If aBuf1(i) <> aBuf2(i) Then MsgBox "不同,位置:" & lCurPos: Exit Do
        lCurPos = lCurPos + 1 '移到下一個待比較位元組的位置
    Next i
   
    k = k + 1
    If k = 100 Then
        k = 0
        Cls
        Print Timer - tmr, "        ", (Seek(cfRead1.FileNumber) / 1024) / (Timer - tmr) & " KB/s"
    End If
Loop Until nActual < BUFFER_SIZE

cfRead1.CloseFile '關檔案
cfread2.CloseFile

MsgBox "OK! " & Timer - tmr

End Sub

---------------------------------------------------------------------------------------------------------------------------------------

'-------------------------------------------------------------------------------------------------------------------------'

完整的VB工程檔案可從這裡下載

http://lqweb.nease.net/cn/mycode/FileReadBlockFileWriteBlock.zip

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.