● ファイルの読み込み方法各種 ●

ここではファイルの読み込んでテキストボックスに表示する方法を紹介する。だけんど、あたしゃぁVBの限界を感じちゃったさ。

まずはAPI関数を使用する方法を紹介する。ここで注意を1つ。CloseHandle 関数できちんとファイルのハンドルを解放しないと大変なことになる。VB の Open ステートメントと違い、異常終了してもファイルハンドルを解放してくれないんだよね。だから開きっぱなしの状態になる。ちなみに見て分かると思うけど、エラー処理は実装していませんぜ。

'ファイルハンドルを取得する
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long

'ファイルから読み込む
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long

'ファイルハンドルを閉じる
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Const GENERIC_ALL = &H10000000
Private Const GENERIC_EXECUTE = &H20000000
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000

Private Const OPEN_EXISTING = 3

'-------------------------------------------------------------------
' 関数名 :  ReadFileUsingAPIFunc
' 機能   : ファイルから文字列を読み込みテキストボックスに表示する
' 引数   : (in) srcText … 文字列を表示するテキストボックス
'           (in) fPath … 読み込むファイルのパス
' 返り値 : なし
'-------------------------------------------------------------------
Public Sub ReadFileUsingAPIFunc(ByVal srcText As TextBox, ByVal fPath As String)

    Dim hFile As Long        'ファイルのハンドル
    Dim FileSize As Long    'ファイルサイズ
    Dim gBinData() As Byte  '取得データ
    Dim outFileSize As Long

    'ファイルを開く
    hFile = CreateFile(fPath, GENERIC_READ, 0&, 0&, OPEN_EXISTING, 0&, 0&)

    'ファイルサイズ取得
    FileSize = FileLen(fPath)

    '変数初期化
    ReDim Preserve gBinData(FileSize - 1) As Byte

    'ファイル読み込み
    Call ReadFile(hFile, gBinData(0), FileSize, outFileSize, 0&)

    'ANSI → Unicode変換
    srcText.Text = StrConv(gBinData(), vbUnicode)

    'ファイルを閉じる
    Call CloseHandle(hFile)

End Sub
次は、ファイルの内容をバイト配列に読みこむ方法を紹介する。

'-------------------------------------------------------------------
' 関数名 :  ReadTextFileAsBinary
' 機能   : ファイルから文字列を読み込みテキストボックスに表示する
' 引数   : (in) srcText … 文字列を表示するテキストボックス
'            (in) fPath … 読み込むファイルのパス
' 返り値 : なし
'-------------------------------------------------------------------
Public Sub ReadTextFileAsBinary(ByVal srcText As TextBox, ByVal fPath As String)

    Dim BufData() As Byte  '文字列格納用バッファ(バイト配列)
    Dim FileSize As Long    'ファイルサイズ
    Dim FileNum As Integer  'ファイルナンバー

    FileNum = FreeFile

    Open fPath For Binary As FileNum
        FileSize = LOF(FileNum)
        ReDim Preserve BufData(FileSize - 1) As Byte 'メモリー再確保
        BufData() = InputB(FileSize, FileNum)
    Close FileNum

    'ANSI → Unicode 変換
    srcText.Text = StrConv(BufData(), vbUnicode)

End Sub
で、最後はファイルの内容を文字列変数に読みこむ方法を紹介する。

'-------------------------------------------------------------------
' 関数名 :  ReadTextFileAsText
' 機能   : ファイルから文字列を読み込みテキストボックスに表示する
' 引数   : (in) srcText … 文字列を表示するテキストボックス
'            (in) fPath … 読み込むファイルのパス
' 返り値 : なし
'-------------------------------------------------------------------
Public Sub ReadTextFileAsText(ByVal srcText As TextBox, ByVal fPath As String)

    Dim BufData As String  '文字列格納用バッファ
    Dim FileNum As Integer 'ファイルナンバー

    FileNum = FreeFile

    Open fPath For Binary As FileNum
        BufData = Input(LOF(FileNum), FileNum)
    Close FileNum

    srcText.Text = BufData

End Sub


実は、ここからが面白くなるんだな。ここで紹介した関数を上から@ABと番号をつけて、各関数におけるファイル読み込み時間を挙げてみる。実行環境は、

        機種:Compaq DeskPro
        Pentium:100MHZ、 RAM:64MB、 HDD:1GB

        OS:Microsoft Windows NT + Service Pack 2
        言語:Visual Basic 5.0 Enterprise Edition + Service Pack 3

というおんぼろ環境の下で 50000バイトの普通のテキストファイルを読み込みました。はい。で、結果は以下の通り。

関数ファイルを読みこむ時間テキストボックスに表示されるまでの時間
@6.00637.90
A1260.601861.70
B1469.002076.45
(20回平均、単位:ミリ秒)
 
驚いた!! @とBの読み込む速さに差がありすぎ!! テキストボックスに表示されるまでの差は3倍もある。…ちょっと問題だなこりゃ。これを知ってしまったら、Openステートメント なんか使っていられなくなるね。やっぱりAPIを使う方がいいみたい。Openステートメントを使用する方法に関して、VBではファイルは文字列変数に読み込むよりもバイト型の配列で読み込む方が速いと言われているが、AとBを見比べてみると、まぁその通りであるが、それほど差があるっていうわけでもないみたい。ここでの結論は、大きいサイズのテキストファイルを読み込むときは、API関数を使った方が効率がいいということだ。エラートラップさえきちっとすれば@の方法がベストであることは言うまでもない!! うりゃぁ〜。

戻る