INIファイルというと今更感がありますが、 簡単にプログラムの動作パラメータなどを保存しておくには便利な機能です。 私もプログラムの変更なしに、外からタイミングの時間の値を後から少し変えたい場合によく使います。
INIファイルの構造は以下の様になります。
[SECTION1] KEY1=keydata1 KEY2=keydata2 [SECTION2] KEYA=keydataA ...
■セクション
[ ] で囲まれた部分がセクションで、各セクションの中にキー文字列を宣言します。
■キー
各セクションの中に宣言される文字列で、その値を = で定義します。
セクションが異なれば、同じキーが在ってもOKです。
■コメント
先頭に ;(セミコロン) を置くとその行はコメント行とみなされます。
また、行の途中に ;(セミコロン) が在ると、それ以降はコメントであるとみなされます。
■エスケープシーケンス
キーの値の文字列として ;(セミコロン) :(コロン) =(等号) #(シャープ) の各文字を含めたい場合があります。その時には各文字の前に \(円マーク) を置きエスケープしてやります。
(以下のソースのクラスではエスケープシーケンスの設定と解除を関数化しています)
以下にINIファイルを取り扱うクラスのソースを示します。
INIファイル読み書きクラス
Imports System.Text
Imports System.Runtime.InteropServices
Public Class ClsIni
'プロファイル文字列取得
'Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" ( _
' ByVal lpApplicationName As String, _
' ByVal lpKeyName As String, _
' ByVal lpDefault As String, _
' ByVal lpReturnedString As System.Text.StringBuilder, _
' ByVal nSize As UInt32, _
' ByVal lpFileName As String) As UInt32
'宣言修正
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" ( _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpApplicationName As String, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpKeyName As String, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpDefault As String, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpReturnedString As StringBuilder, _
ByVal nSize As UInt32, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpFileName As String) As UInt32
'プロファイル文字列書込み
'Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" ( _
' ByVal lpAppName As String, _
' ByVal lpKeyName As String, _
' ByVal lpString As String, _
' ByVal lpFileName As String) As Integer
'宣言修正
Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" ( _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpAppName As String, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpKeyName As String, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpString As String, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpFileName As String) As Integer
Private strIniFileName As String = ""
'''
''' コンストラクタ
'''
''' <param name="strIniFile">INIファイル名(フルパス)</param>
Sub New(ByVal strIniFile As String)
Me.strIniFileName = strIniFile 'ファイル名退避
End Sub
'''
''' プロファイル文字列取得
'''
''' <param name="strAppName">アプリケーション文字列</param>
''' <param name="strKeyName">キー文字列</param>
''' <param name="strDefault">デフォルト文字列</param>
''' プロファイル文字列
Public Function GetProfileString(ByVal strAppName As String, _
ByVal strKeyName As String, _
ByVal strDefault As String) As String
Try
Dim strWork As System.Text.StringBuilder = New System.Text.StringBuilder(1024)
Dim intRet As Integer = GetPrivateProfileString(strAppName, strKeyName,
strDefault, strWork,
strWork.Capacity - 1, strIniFileName)
If intRet > 0 Then
'エスケープ文字を解除して返す
Return ResetEscape(strWork.ToString())
Else
Return strDefault
End If
Catch ex As Exception
Return strDefault
End Try
End Function
'''
''' プロファイル文字列設定
'''
''' <param name="strAppName">アプリケーション文字列</param>
''' <param name="strKeyName">キー文字列</param>
''' <param name="strSet">設定文字列</param>
''' True:正常, False:エラー
Public Function WriteProfileString(ByVal strAppName As String, _
ByVal strKeyName As String, _
ByVal strSet As String) As Boolean
Try
'エスケープ文字変換
Dim strCnv As String = SetEscape(strSet)
Dim intRet As Integer = WritePrivateProfileString(strAppName, strKeyName, strCnv, strIniFileName)
If intRet > 0 Then
Return True
Else
Return False
End If
Catch ex As Exception
Return False
End Try
End Function
'''
''' エスケープ文字変換
'''
''' <param name="strSet">設定文字列</param>
''' 変換後文字列
Private Function SetEscape(ByVal strSet As String) As String
Dim strEscape As String = ";#=:"
Dim strRet As String = strSet
Try
For i = 0 To strEscape.Length - 1
Dim str As String = strEscape.Substring(i, 1)
strRet = strRet.Replace(str, "\" & str)
Next
Return strRet
Catch ex As Exception
Return ""
End Try
End Function
'''
''' エスケープ文字解除
'''
''' <param name="strSet">設定文字列</param>
''' 変換後文字列
Private Function ResetEscape(ByVal strSet As String) As String
Dim strEscape As String = ";#=:"
Dim strRet As String = strSet
Try
For i = 0 To strEscape.Length - 1
Dim str As String = strEscape.Substring(i, 1)
strRet = strRet.Replace("\" & str, str)
Next
Return strRet
Catch ex As Exception
Return ""
End Try
End Function
End Class
このクラスを利用する例を以下に記します。 このボタン処理内では、最初にINIファイルへの書き込みを行い、その後でそのINIファイルからの読込を行っています。
Private Sub ButtonIni_Click(sender As Object, e As EventArgs) Handles ButtonIni.Click
'自分自身の存在するフォルダ
Dim strPath As String = System.IO.Path.GetDirectoryName(Application.ExecutablePath)
'INIファイルクラスの生成
Dim Ini As New ClsIni(strPath & "\TEST.INI")
'INIファイルへの書込みテスト
Ini.WriteProfileString("SECTION1", "DATA1", "test-data-1:aaa")
Ini.WriteProfileString("SECTION1", "DATA2", "test-data-2;bbb")
Ini.WriteProfileString("SECTION2", "DATA1", "TEST-DATA-1=:;#AAA")
'INIファイルからの取得テスト
Dim str As String
str = Ini.GetProfileString("SECTION1", "DATA1", "default-data-1:aaa")
Console.WriteLine("SECTION1:DATA1=" & str)
str = Ini.GetProfileString("SECTION1", "DATA2", "default-data-2;bbb")
Console.WriteLine("SECTION1:DATA2=" & str)
str = Ini.GetProfileString("SECTION2", "DATA1", "default-DATA-1=:;#AAA")
Console.WriteLine("SECTION2:DATA1=" & str)
str = Console.ReadLine()
End Sub
INIファイルへの書込みでエスケープしないといけない文字を含んでいますので、 このプログラムを実行し「TEST.INI」をテキストエディタで確認すると、 \(円マーク) が付加されて書き込まれているのがわかるはずです。 関連する記事
⇒XMLファイルをINIファイルの様に扱う処理:[XmlDocument,XmlElement,CreateElement]おすすめ本
PR
コメント
1. RPGゲームやシミュレーションなどのセーブとロードの実装について
ブログをよく拝見させていただいております
現在vb.netにて簡単なゲームの制作の方をしているのですが、どうもセーブとロードの実装が出来ていません
通常のゲームのようにセーブボタンを押したら現在の情報を保存し、ロードを押したらそれをもとに復元させることを行いたいんですが何かアドバイスをいただくことはできませんか?
クリックイベントに変数を記載しセレクト文で分岐させている状態です。
2. 無題
お名前が記載されていますが、お名前がご自身のものならば、何かハンドル名を使われる方が宜しいかと思います。
さて、プログラムの状態をセーブ・ロードを行いたいとのことですが、このINIファイルを使う場合には
プログラムの各情報をセクション名とキー名で分けてセーブされるといいと思います。
セーブされるデータは文字列指定のため、数値を文字列化してから設定して下さい。
また、ロードの場合は数値項目の場合は、文字列からの変換が必要かと思います。
以上、内容的に外していたらすみません。
では失礼します。
3. 無題
勉強になります
軽いサンプルコードなど記載してはいただけないでしょうか?
何分セーブとロードの実装処理に1か月以上苦しんでおり、何分vb.netはゲーム制作での資料が少なくどうしたらいいのか分からないんです
変数を全てテキストに起こしてそこから読み込むということは分かるのですが、どうコードの方を記載したらそのような処理が出来るのか見当もつきません
サンプルコードや上記のやり方など軽くでもいいので教えて頂けませんか?
管理人様ならこう作るかな的なことでもいいんです
宜しくお願いします
4. 無題
変数全てを構造体もしくはクラスの中に全て持っておき、そのオブジェクトをシリアライズ化して1個のデータファイルに書き込みます。
この時のデータファイルはバイナリデータで書き込みます。
■ロード
セーブされたデータファイルを読込、デシリアライズしてもとの構造体に設定します。
例としてMicrosoftのサイトに載っていましたのでご確認下さい。
https://msdn.microsoft.com/ja-jp/library/cc708907.aspx
この例を参考にすればできると思います。
尚、このページのINIファイルは使用してはいませんが...
現在プログラミングの仕事で忙しいので、検証はしていませんが、時間が出来ましたら、
別の課題としてアップしたいと思います。
以上、宜しくお願い致します。
5. 無題
是非別の課題としての検証の方よろしくお願いします
6. 無題
7. ありがとうございました
この度はありがとうございました
8. 無題
ようやく目標にしていた実装が出来ました。
これも管理人様のアドバイスのおかげです。
ありがとうございました
9. 無題
今回の件は、また時間が出来た時点で、アップしたいと思いますので、
また、ご覧頂ければと思います。
10. INIファイルの読込
以下ですが、strPathに日本語が含まれていると一つ上のフォルダに「・」という拡張子も何も無い謎のファイルが作られて
iniファイルが作られません。日本語を含んでいない場合は上手くいきます。
'INIファイルクラスの生成
Dim Ini As New ClsIni(strPath & "\TEST.INI")
お時間のあるときに日本語のパスに対応したサンプルを掲載して頂けるとうれしいのですが・・・。
不躾に厚かましいお願い申し訳ありません。
11. 無題
クラス内のAPIの宣言を修正しましたので、これでお試しください。
12. 上手くいきました!!
迅速なご対応ありがとうございました。