またサンプルにはVBではまったくなじみがないと思われる strstr が使用されている。これに関する話題と言うかネタはVBでstrstrを使用して文字列検索するを参照されたい。
メモリマップドファイルによるメモリ(文字列ポインタ)の取得方法は極めて簡単である。
'ファイルハンドル Private m_hFile As Long 'メモリマップドファイルのハンドル Private m_hMapp As Long 'ファイル内容(文字列)のポインタ Private m_lpData As Long '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ' 機 能:ファイルを開いて、マッピングオブジェクトを作成する ' 引 数:(i)FileName … ファイル名 ' (i)IsReadOnly … 読み取り専用にする場合はTrue ' 返り値:正常…True 異常…False '=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Private Function OpenFile(ByVal FileName As String, _ Optional ByVal IsReadOnly As Boolean = False) As Boolean 'ファイルを開く m_hFile = CreateFile(FileName, GENERIC_READ Or IIf(IsReadOnly, 0, GENERIC_WRITE), 0, 0, OPEN_EXISTING, 0, 0) If m_hFile = INVALID_HANDLE_VALUE Then Exit Function 'メモリマップドファイルを作成する If IsReadOnly Then m_hMapp = CreateFileMapping(m_hFile, 0, PAGE_READONLY, 0, 0, 0&) Else m_hMapp = CreateFileMapping(m_hFile, 0, PAGE_READWRITE, 0, 0, 0&) End If If m_hMapp = 0 Then Exit Function 'ファイル内容(文字列)のポインタを取得 m_lpData = MapViewOfFile(m_hMapp, IIf(IsReadOnly, FILE_MAP_READ, FILE_MAP_WRITE), 0, 0, 0) If m_lpData = 0 Then Exit Function '正常終了 OpenFile = True Exit Function ErrHandler: 'ファイルを閉じる Call CloseFile End Function '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ' 機 能:ファイルを閉じる ' 引 数:なし ' 返り値:なし '=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Private Sub CloseFile() 'ファイル内容(文字列)のポインタを開放する If m_lpData Then Call UnmapViewOfFile(m_lpData) m_lpData = 0 End If 'メモリマップドファイルのハンドルを破棄する If m_hMapp Then Call CloseHandle(m_hMapp) m_hMapp = 0 End If 'ファイルを閉じる If m_hFile Then Call CloseHandle(m_hFile) m_hFile = 0 End If End Sub OpenFile を実行し正常に動作すると、m_lpData変数にファイルデータのポインタが設定される。m_lpDataをあれこれ操作してこれ以上行う処理が無くなったら CloseFile を実行して、色々なものを閉じる。基本的な処理はこれだけで本当に簡単。 ファイルデータはメモリに展開され、そのメモリの位置、要するにポインタがm_lpData変数に格納される。ということは、C言語的文字列関数でデータを色々と操作できるわけである。strlen(m_lpData) とすれば文字列のバイト数(=ファイルサイズ)を取得できるし、strncpy(m_lpData + 3, "ABC", 3) とすれば先頭4バイト目から6バイト目をABCに書き換えられる(但し7バイト目にはNULL文字が設定される)し、FillMemory(m_lpData + 10, 10, Asc("A")) とすれば11バイト目から20バイト目をAに書き換えられる。処理も幾分速そうである。 上記のような書き方をすると、テキストファイルしか扱えないと思われるが、そんなことは無いのでご安心をば。メモリマップドファイルはNULL文字までしか読まないということは無くファイル全体を読んでくれるので、バイナリファイルも余裕で扱える。この場合、構造体などのデータのやり取りは strcpy や strlen のような文字列関数ではなく、CopyMemory を使用して行う。取り立てて難しいことはない。 メモリマップドファイルを読み書きモード(PAGE_READWRITE)で作成している場合は、書き換えた内容を Call FlushViewOfFile(m_lpData, 0) とすることで即座にファイル出力できる。メモリサイズを動的に変更してファイル出力できるかは調査不足で不明であるが、メモリサイズを変えないデータ変更処理が必要な場合は極めて有用である。じゃあそれってどんな場合か、と考えてみたもののそれほど多くは思い浮かばなかったが、大文字→小文字変換、ビットマップの色変換などで使用できそうである。 この方法を知ってしまったら、テキストファイルを開いて、その内容を String 変数に設定して何らかの処理を行う、という今までやってきた作業がアホらしくなるかもしれない。それはともかく、いつでも使えるようにクラス化しておくと良いかもしれないですな。 |