web-dev-qa-db-ja.com

GetPrivateProfileStringを使用してすべてのiniファイル値を読み取ります

StringBuilder変数内のiniファイルのすべてのセクション/キーを読み取る方法が必要です。

[DllImport("kernel32.dll")]
private static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName);

...

private List<string> GetKeys(string iniFile, string category)
{
    StringBuilder returnString = new StringBuilder(255);            

    GetPrivateProfileString(category, null, null, returnString, 32768, iniFile);

    ...
}

ReturnStringでは、最初のキー値のみです。一度にすべてを取得してStringBuilderとListに書き込むにはどうすればよいですか?

ご協力ありがとうございました!

leon22に挨拶

11
leon22

考えられる解決策:

[DllImport("kernel32.dll")]
private static extern int GetPrivateProfileSection(string lpAppName, byte[] lpszReturnBuffer, int nSize, string lpFileName);

private List<string> GetKeys(string iniFile, string category)
{

    byte[] buffer = new byte[2048];

    GetPrivateProfileSection(category, buffer, 2048, iniFile);
    String[] tmp = Encoding.ASCII.GetString(buffer).Trim('\0').Split('\0');

    List<string> result = new List<string>();

    foreach (String entry in tmp)
    {
        result.Add(entry.Substring(0, entry.IndexOf("=")));
    }

    return result;
}
19
leon22

役立つGetPrivateProfileSection()もあると思いますが、Zenwalkerに同意します。これに役立つライブラリがあります。 INIファイルはそれほど読みにくいものではありません。セクション、キー/値、コメントはほとんどそれです。

2
Neil Barnwell

IniReaderライブラリを使用してINIファイルを読み取らないのはなぜですか??その方法でより簡単かつ高速になります。

1
Zenwalker
Dim MyString    As String = String.Empty
Dim BufferSize As Integer = 1024 
Dim PtrToString As IntPtr = IntPtr.Zero
Dim RetVal As Integer
RetVal = GetPrivateProfileSection(SectionName, PtrToString, BufferSize, FileNameAndPah)

関数呼び出しが成功すると、結果がPtrToStringメモリアドレスに取得され、RetValには文字列の長さがPtrToStringに含まれます。それ以外の場合、十分なBufferSizeがないためにこの関数が失敗した場合、RetValにはBufferSize-2が含まれます。したがって、これを確認して、より大きなBufferSizeを使用してこの関数を再度呼び出すことができます。

'これが、メモリアドレスから文字列を取得する方法です。

MyString = Marshal.PtrToStringAuto(PtrToString, RetVal - 1)

'ここでは、余分なnull文字列を避けるために、「RetVal-1」を使用します。

'次に、null文字が来る文字列を分割する必要があります。

Dim MyStrArray() As String = MyString.Split(vbNullChar)

したがって、この配列には、その特定のセクションのすべてのKey-Valueペアが含まれます。そして、メモリを解放することを忘れないでください

Marshal.FreeHGlobal(PtrToString)
0
Vinod KC

これらのルーチンは、INIセクション全体を読み取り、セクションを生の文字列のコレクションとして返します。各エントリは、INIファイル( INI構造体を使用しているが、必ずしも=)を持っているとは限らない場合や、セクション内のすべてのエントリのキーと値のペアのコレクションを返す場合に便利です。

    [DllImport("kernel32.dll")]
    public static extern uint GetPrivateProfileSection(string lpAppName, IntPtr lpReturnedString, uint nSize, string lpFileName);

    // ReSharper disable once ReturnTypeCanBeEnumerable.Global
    public static string[] GetIniSectionRaw(string section, string file) {
        string[] iniLines;
        GetPrivateProfileSection(section, file, out iniLines);
        return iniLines;
    }

    /// <summary> Return an entire INI section as a list of lines.  Blank lines are ignored and all spaces around the = are also removed. </summary>
    /// <param name="section">[Section]</param>
    /// <param name="file">INI File</param>
    /// <returns> List of lines </returns>
    public static IEnumerable<KeyValuePair<string, string>> GetIniSection(string section, string file) {
        var result = new List<KeyValuePair<string, string>>();
        string[] iniLines;
        if (GetPrivateProfileSection(section, file, out iniLines)) {
            foreach (var line in iniLines) {
                var m = Regex.Match(line, @"^([^=]+)\s*=\s*(.*)");
                result.Add(m.Success
                               ? new KeyValuePair<string, string>(m.Groups[1].Value, m.Groups[2].Value)
                               : new KeyValuePair<string, string>(line, ""));
            }
        }

        return result;
    }
0
Wade Hatler