[VB2010]INIファイルを読み書きする
ここではWindowsAPIを使ったINIファイル操作を紹介します。これはAPIを使えばWindowsのINIファイル形式のものが比較的簡単に読み書きできるものですが、データのセーブやロードにINIファイルが便利かどうかは良くわかりません。INIファイルを利用したい人は参考にどうぞ。
まずはINIファイルの構造から説明しましょう…と思ったのですが、INIファイルの各要素の正式名称がわからなかったので、当局では次の名前を使用します。
[ section ] | … 各カッコ内を「セクション」と呼ぶ |
key1 = value1 | |
key2 = value2 | … イコールの左辺を「キー」、右辺を「値」と呼ぶ |
key3 = value3 |
これ以後の説明には次のサンプルINIファイルを使用します。
[SAMPLE] key1=12534 key2=ファイル入出力 key3=aaaa |
値の読み取り - その1
まずは基本的な「セクションとキーを指定して値を取得する」というのをやってみましょう。使用するWindowsAPIはGetPrivateProfileIntと、GetPrivateProfileStringです。名前から判断できるように、前者は値を数値として取得し、後者は値を文字列として取得します。
Declare Function GetPrivateProfileInt Lib "kernel32" Alias "GetPrivateProfileIntA" ( _ ByVal lpApplicationName As String,_ ByVal lpKeyName As String,_ ByVal nDefault As Integer,_ ByVal lpFileName As String) As Integer |
引数名 | 説明 |
---|---|
lpApplicationName | INIファイル内のセクション名 |
lpKeyName | セクション内のキー名 |
nDefault | キーが見つからない時のデフォルト値 |
lpFileName | INIファイルのパス |
返り値はINIファイルから取得した値となります。キーが見つからない時は nDefaultの値が返ります。仕組みとしてはファイルから取得した文字を、Integer型のコンストラクタに入れた結果が返ると考えて良いでしょう。
では実行例を見てみましょう。
Const DEF_VAL As Long = 0 Dim iniFileName As String = Application.StartupPath & "\test.ini" 'INIファイル名 Dim intVal As Integer = GetPrivateProfileInt("SAMPLE","key1",DEF_VAL,iniFileName) |
前述のINIファイルから正しく読み取ると、intValには12534が格納されます。
Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" ( _ ByVal lpApplicationName As String,_ ByVal lpDefault As String,_ ByVal lpReturnedString As String,_ ByVal nSize As Integer,_ ByVal lpFileName As String) As Integer |
引数名 | 説明 |
---|---|
lpApplicationName | INIファイル内のセクション名 |
lpKeyName | セクション内のキー名 |
lpDefault | キーが見つからない時のデフォルト値 |
lpReturnedString | 取得した文字列の格納領域 |
nSize | 格納領域のバイト数 |
lpFileName | INIファイルのパス |
返り値はlpReturnedStringに格納したサイズ(バイト数)となります。INIファイルから取得した文字列は lpReturnedString に渡されます。そのため、この変数には十分なサイズを確保しておかなければなりません。
では実行例を見てみましょう。
Const DEF_STR As String = vbNullString Dim buffer As String = New String(" ",1024) 'Spaceが1024文字 Dim iniFileName As String = Application.StartupPath & "\test.ini" 'INIファイル名 Dim ret As Integer = GetPrivateProfileString( _ "SAMPLE","key2",DEF_STR,buffer,buffer.Length,iniFileName _ ) Dim strVal As String = buffer.SubString(0,buffer.IndexOf(vbNullChar)) |
前述のINIファイルから正しく読み取ると、strValには"ファイル入出力"が格納されます。
ただし、文字列の取得方法には注意する必要があります。まずGetPrivateProfileStringを呼び出す前に格納変数bufferに対し、領域を割り当てなければなりません。つまり格納領域として使用する変数にはあらかじめ必要以上サイズを確保しておかなければなりません。この領域を確保しておかないと読み取ることができません。
また引数lpReturnedStringのサイズを越えて引数nSizeを指定すると動作を保証できません。当局の場合次のように実行すると強制終了となりました。第5引数は直接指定せずにLengthプロパティを用いるべきです。
Dim buffer As String = New String(" ",255) Dim ret As Integer = GetPrivateProfileString( _ "SAMPLE",256,iniFileName _ ) 'bufferのサイズは255なのに無理矢理256あると指定すると強制終了となった |
領域を確保した後にGetPrivateProfileStringを呼び出すと、bufferには次のような形式で格納されます。
フ | ァ | イ | ル | 入 | 出 | 力 | _ | … |
注意 : "_"はNull文字(vbNullChar)を表す。
このように、文字列の終端にはNull文字(vbNullChar)がついています。これをIndexOfメソッドおよびSubStringメソッドを使って終端の手前までの文字列を切り出せば正しく文字列を取得することができます。なお終端のvbNullCharより後ろについては何も変更されません。この例ではStringクラスのコンストラクタにて(意図的に)半角空白で領域を確保したため9文字目以降が空白になっています。
返り値はファイル上のバイトサイズ(例えばShift_JIS文字コードセットでのバイト数)です。
値の書き込み - その1
ここでは、「セクションとキーを指定して値を書き込む」ことをやってみましょう。使用するWindowsAPIはWritePrivateProfileStringです。書き込みは全て文字列で行うため、数値を書き込むときはToStringメソッドを使うなどして文字列に変換します。
Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" ( _ ByVal lpApplicationName As String,_ ByVal lpString As String,_ ByVal lpFileName As String) As Integer |
引数名 | 説明 |
---|---|
lpApplicationName | INIファイル内のセクション名 |
lpKeyName | セクション内のキー名 |
lpString | 書き込む文字列 |
lpFileName | INIファイルのパス |
返り値は成功/失敗の真偽値です。
では実行例を見てみましょう。
Dim ret As Integer '関数の返り値 Dim iniFileName As String = Application.StartupPath & "\test.ini" 'INIファイル名 Dim intItem As Integer = 12534 '書き込む値(数値) Dim strItem As String = "ファイル入出力" '書き込む値(文字) ret = WritePrivateProfileString("SAMPLE",intItem.ToString(),iniFileName) ret = WritePrivateProfileString("SAMPLE",strItem,iniFileName) |
出力イメージは次の通りです。
[SAMPLE] key1=12534 key2=ファイル入出力 |
値の読み取り - その2
「値の読み取り - その1」では1つのキーの値を取得しました。でもキーが複数個あるときにいちいち1つずつ取得するのも大変です。そこで特定のセッション内の全ての「キーと値の組」を取得することもできます。使用するWindowsAPIはGetPrivateProfileSectionです。
Declare Function GetPrivateProfileSection Lib "kernel32" Alias "GetPrivateProfileSectionA" ( _ ByVal lpAppName As String,_ ByVal lpFileName As String) As Integer |
引数名 | 説明 |
---|---|
lpAppName | INIファイル内のセクション名 |
lpReturnedString | 取得した文字列の格納領域 |
nSize | 格納領域のバイト数 |
lpFileName | INIファイルのパス |
返り値はlpReturnedStringに格納したサイズ(バイト数)となります。INIファイルから取得した文字列は lpReturnedString に渡されます。そのため、この変数には十分なサイズを確保しておかなければなりません。
lpReturnedStringに格納される文字列は次のようになります。
k | e | y | 1 | = | v | a | l | u | e | 1 | _ | k | e | y | 2 | = | v | a | l | u | e | 2 | _ | k | e | y | 3 | = | v | a | l | u | e | 3 | _ | _ |
注意 : "_"はNull文字(vbNullChar)を表す。
つまり、"キー=値"という組の末尾にvbNullCharを入れることで区切りを示し、組の羅列を1文で作成します。文末は組の末尾と文字列全体の末尾という意味でvbNullCharを2文字続けて締めくくります。
では実行例を見てみましょう。
Dim buffer As String = New String(" ",1024) Dim iniFileName As String = Application.StartupPath & "\test.ini" 'INIファイル名 Dim ret As Integer = GetPrivateProfileSection( _ "SAMPLE",buffer.IndexOf(vbNullChar & vbNullChar)) |
このコードはGetPrivateProfileStringの実行例とよく似ています。ただしstrValを切り出したところで、それぞれのキーと値がわかるわけではありません。ここでは組の羅列を一旦切り出したことになります。この後さらに文字列操作をして1つ1つを取り出す必要があります。
最も手っ取り早いのはSplitメソッドを使いvbNullCharを区切り文字にして配列に格納することです。
Dim strArray() As String strArray = strVal.Split(vbNullChar) |
これによりstrArray(0)が1番目のキーと値、strArray(1)が2番目のキーと値、…というように格納されます。i番目のキーと値がstrArray(i - 1)となるわけですね。キーと値を分けるにはさらに"="で分割することになります。
ちなみに配列のインデックスは0から始まります。また要素数はLengthプロパティで取得できます。strArray.Length = n の時、要素は 0 から n - 1 までの n 個あるということです。次の例は"SAMPLE"セクションのキーと値を順に表示します。
Public Class Class1 Declare Function GetPrivateProfileSection Lib "kernel32" Alias "GetPrivateProfileSectionA" ( _ ByVal lpAppName As String,_ ByVal lpFileName As String) As Integer Private Sub GetSection1() Dim strArray() As String Dim buffer As String = New String(" ",1024) Dim iniFileName As String = Application.StartupPath & "\test.ini" 'INIファイル名 Dim ret As Integer = GetPrivateProfileSection("SAMPLE",iniFileName) Dim strVal As String = buffer.SubString(0,buffer.IndexOf(vbNullChar & vbNullChar)) strArray = strVal.Split(vbNullChar) For i As Integer = 0 To strArray.GetUpperBound(0) Dim k As Integer = strArray(i).IndexOf("=") MessageBox.Show(i + 1 & "番目" & vbCrLf & _ "キー:" & strArray(i).SubString(0,k - 1) & vbCrLf & _ "値:" & strArray(i).SubString(k + 1)) Next End Sub End Class |
あるいはFor Each文を用いたり、キーと値の分割に再びSplitメソッドを用いることも考えられますね。
Public Class Class2 Declare Function GetPrivateProfileSection Lib "kernel32" Alias "GetPrivateProfileSectionA" ( _ ByVal lpAppName As String,_ ByVal lpFileName As String) As Integer Private Sub GetSection2() Dim strArray() As String Dim buffer As String = New String(" ",buffer.IndexOf(vbNullChar & vbNullChar)) strArray = strVal.Split(vbNullChar) Dim i As Integer = 0 For Each strItem As String In strArray Dim s() As String s = strItem.Split("=") MessageBox.Show(i + 1 & "番目" & vbCrLf & _ "キー:" & s(0) & vbCrLf & _ "値:" & s(1)) i += 1 Next End Sub End Class |
値の書き込み - その2
先ほどセクション丸ごと値の取得を行いましたので、その反対であるセクション丸ごと値の書き込みもできます。使用するWindowsAPIはWritePrivateProfileSectionです。
Declare Function WritePrivateProfileSection Lib "kernel32" Alias "WritePrivateProfileSectionA" ( _ ByVal lpAppName As String,_ ByVal lpFileName As String) As Integer |
引数名 | 説明 |
---|---|
lpAppName | INIファイル内のセクション名 |
lpString | 書き込む文字列 |
lpFileName | INIファイルのパス |
返り値は成功/失敗の真偽値です。
書き込む文字列lpStringはGetPrivateProfileSectionで紹介したように、"キー=値"の組み合わせをvbNullCharで連結し、文末はvbNullCharを2つ付けた文字列にします。
では実行例を見てみましょう。
Dim iniFileName As String = Application.StartupPath & "\test.ini" 'INIファイル名 Dim strItem As String = "key1=12534" & vbNullChar & "key2=ファイル入出力" & vbNullChar & vbNullChar '書き込む値(文字) Dim ret As Integer = WritePrivateProfileSection("SAMPLE",iniFileName) |
出力イメージは次の通りです。
[SAMPLE] key1=12534 key2=ファイル入出力 |