忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

INIファイル読み書き処理

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ファイルの読込

どうも、初めまして。VB2017でINIファイルを使いたいという今さらなプログラムを構想していてこのページに辿り着きました。
以下ですが、strPathに日本語が含まれていると一つ上のフォルダに「・」という拡張子も何も無い謎のファイルが作られて
iniファイルが作られません。日本語を含んでいない場合は上手くいきます。

'INIファイルクラスの生成
Dim Ini As New ClsIni(strPath & "\TEST.INI")

お時間のあるときに日本語のパスに対応したサンプルを掲載して頂けるとうれしいのですが・・・。
不躾に厚かましいお願い申し訳ありません。

11. 無題

コメント有難うございます。
クラス内のAPIの宣言を修正しましたので、これでお試しください。

12. 上手くいきました!!

日本語フォルダで上手くいきました!!
迅速なご対応ありがとうございました。
コメントを書く