GetPrivateProfileString関数は遅い

INIファイルの取得にGetPrivateProfileString関数を使うことがあります。

ただ、GetPrivateProfileString関数にはいくつかの問題があります。

  • 処理が遅い。
  • 値取得用の変数を事前に拡張しておく必要がある。
  • 値取得後に事前に拡張した領域のうち不要な部分を除去する必要がある。
  • おまけ。Shift-JIS以外のファイルは文字化けする。

対応方法はあります。

INIファイルを自分で読み込んで内容を取得する

処理が遅い点については改善点はあります。INIファイルを事前に全てメモリに格納しておき、処理中に必要になったらメモリを参照する、という方法です。メモリ、と書きましたが、実際にはINIファイル用の構造体(ユーザー定義型)にしておくと使い勝手がよいです。

ただし、それだけでは処理が遅い点以外の問題には対応できません。上記の問題を全て対応するには、そもそもGetPrivateProfileString関数を使わない、という方法を採ります。

具体的には、自分でファイルを読み込んで、キーと値の組み合わせを連想配列に格納し、最終的に構造体に格納する、という方法です。

この方法はINIファイルに設定されている内容が多ければ多いほど、高速化の恩恵を受けます。この記事はこの2点目がメインの内容になります。

なお、INIファイルは一般的にはShift-JISの場合が多いので、以下のサンプルでもINIファイルはShift-JISとしています。UTF-8などの場合は、ADODB.Streamを使ってファイルを参照する必要があります。

その辺りについては「VBAでUTF-8のファイルをShift-JISに変換する」をご参照ください。

処理手順の概要

高速にINIファイルから値を取得するための手順概要は以下になります。

  1. INIファイルを開く。
  2. 1行ずつ読み込む。
  3. キーと値の行であれば内容を連想配列に格納する。
  4. INIファイルを閉じる。
  5. 構造体に登録する内容を1件ずつ連想配列から取得する。

サンプルのINIファイル

以下のサンプルコードで使うINIファイルは以下の構成とします。

セミコロンはコメント行で、セクションが2つあり、それぞれで設定が2つずつあり、空行もある想定です。

 

事前設定

以下のコードでは連想配列のDictionaryクラスを利用しています。

Dictionaryクラスを利用するためには、VBA画面のツールメニュー→参照設定を選び、参照設定ダイアログで「Microsoft Scripting Runtime」にチェックを付けます。

サンプルコード

上記のINIファイルを読み込み、最終的には構造体に格納するまでの流れのサンプルコードです。

 

コード説明

各処理はコメントを書いているので分かると思いますので、考え方を説明します。

まず、INIファイルを開いて1行ずつ読み込んでいきます。

読み込んだ1行がセクション行ならセクション文字列を取得し、キーと値の行ならキー文字列と値文字列を取得します。

キーと値を取得したら、Dictionaryに追加します。

追加する際のDictionaryのキーには、INIファイルのセクションとキーを連結した文字列を指定しています。

ここまでがINIファイルをDictionaryに登録する処理です。

あとは、INIファイルの項目と対になる構造体の各項目にDictionaryのItemメソッドで値を設定します。

Itemメソッドに渡す文字列はセクション文字列とキー文字列を連結させたものになります。

あとはINIファイルの内容が必要になった処理で、構造体の対象項目を参照していくことになります。