iniファイルの取得方法

[戻る]
さくちゃ 2006/07/20(木) 17:44:58
初心者なのですが初めてお世話になります。iniファイルの取得方法について質問なのです。
キー名が
NAME1=***
NAME2=***
NAME3=***
NAME4=***
と複数有りこれをスマートに取得したいのですがいい案が思い浮かびません。
キー名は入力により5・6と増加したり減少したりします。※最低は1・最高は制限なし
GetPrivateProfileStringを試したのですが第2引数のキー名でひっかかりいい案が思い浮
かびません。
今までは増減することがなかったのでキー名はStringTableに必要分だけ書いていたのですが
いくつ増えるのか分からないので上手くいきません。
どうかいい案がありましたら教えてください。

KING・王 2006/07/20(木) 17:53:21
> GetPrivateProfileStringを試したのですが第2引数のキー名でひっかかりいい案が思い浮
かびません。

次のようにキー名を動的に作成しては?
#かなり省略していますが、参考に。

char KeyName[6] = {0x00};

sprintf( KeyName, "NAME%d", i );// iには0〜9の任意の整数値が入る。

GetPrivateProfileString( NULL, KeyName, DataBuf, DataBufSize, IniFileName );

Blue 2006/07/20(木) 17:55:51
> キー名は入力により5・6と増加したり減少したりします。
どこかに、キーがいくつあるかの情報を保持するようなキーを設定したほうがよさそう
です。

; 追加!(キーの数を保持する)
NAMENUM=4

NAME1=***
NAME2=***
NAME3=***
NAME4=***

Blue 2006/07/20(木) 18:08:00
一応過去ログにこんなのあった。

INIファイルのキー名取得の方法 
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200202/02020019.txt

三草 2006/07/20(木) 18:42:18
蛇足ですが、、、

DWORD GetPrivateProfileString(
  LPCTSTR lpAppName,        // セクション名
  LPCTSTR lpKeyName,        // キー名
  LPCTSTR lpDefault,        // 既定の文字列
  LPTSTR lpReturnedString,  // 情報が格納されるバッファ
  DWORD nSize,              // 情報バッファのサイズ
  LPCTSTR lpFileName        // .ini ファイルの名前
);

INIファイルにキー(lpKeyName)が見つからなかった場合、
lpReturnedStringには、lpDefaultの文字列が格納されます。

なので、KING・王さんの案に追加で、lpDefaultで取得し得ない決めの文字列
("ENDDATA"とか)を指定しておき、lpReturnedStringがその文字列ならループ(?)を抜け
る。
としておけば、いくらでも読めるかなと思いました。

KING・王 2006/07/20(木) 21:07:33
> キー名が
> NAME1=***
> NAME2=***
> NAME3=***
> NAME4=***
> と複数有りこれをスマートに取得したいのですがいい案が思い浮かびません。
> キー名は入力により5・6と増加したり減少したりします。※最低は1・最高は制限なし

すいません。
よくよく読むと、キー名が別に"NAME1"や"NAME2"というわけではないですね。
勘違いしていました。

ということで、そのINIファイルにはセクションをつけれるのでしょうか?
セクションがあれば、GetPrivateProfileString()の第1引数にそのセクション名を指定し、
第2引数にNULLを指定すれば、第4引数のバッファに、指定したセクション内のキー名称が、
順番に列挙され、'\0'区切りで格納されます。
例えばINIファイルが
[TEST]
NAME1=***
NAME2=***
NAME3=***
NAME4=***
の場合、"NAME1\0NAME2\0NAME3\0NAME4\0\0"が格納されます。
ただ、GetPrivateProfileString()の第1引数にNULLを指定すると、指定したINIファイル内
のセクションの列挙になってしまうので、
仮に第1引数、第2引数ともにNULLを指定しても、ダメなようです。
ということで、私としては、セクション設定し、第2引数をNULLで指定して列挙するのが、
ベストではないかと思います。

RAPT 2006/07/21(金) 01:35:31
GetPrivateProfileSection() を使えば、セクション以下のデータがまとめて
取得できるので、あとはこれを自前で処理するという方法もあります。

例えばINIファイルが
[TEST]
NAME1=AAA
NAME2=BBB
NAME3=CCC
NAME4=DDD
の場合、"NAME1=AAA\0NAME2=BBB\0NAME3=CCC\0NAME4=DDD\0\0"が格納されます。

\0 で区切れば、"NAME1=AAA" が取得できて、
これを最初の = で区切れば、"NAME1" と "AAA" が取得できます。

キーと値の両方が欲しい場合、潤沢なメモリを使えるなら、こちらの方法の方が速いです。

さくちゃ 2006/07/21(金) 09:41:19
皆様どうもありがとうございます。返信が遅くなり申し訳ございません。
あと、書き方が悪くて申し訳ございませんでした。上記で書いたやつにはセクションはあ
ります。
RAPT様が書いてある通り一つのセクションに不特定多数のキーがあり、キー値だけを抜き
取りたいです。
[TEST]
NAME1=AAA
NAME2=BBB
NAME3=CCC
NAME4=DDD

>>KING・王様
>char KeyName[6] = {0x00};
>sprintf( KeyName, "NAME%d", i );// iには0〜9の任意の整数値が入る。
>GetPrivateProfileString( NULL, KeyName, DataBuf, DataBufSize, IniFileName );

今はそれと似た形でとりあえず作ってはいるのですが、どこにどう保持しようかとなやん
でいて…あとで抜き取った情報をリストボックスかコンボボックスに表示しようと思って
いるのですが、どう保持した方が後々楽でしょうか?

>ということで、そのINIファイルにはセクションをつけれるのでしょうか?
セクションはあります。申し訳ございません。

>第2引数にNULLを指定すれば、第4引数のバッファに、指定したセクション内のキー名
称が、
>順番に列挙され、'\0'区切りで格納されます。
>例えばINIファイルが
>[TEST]
>NAME1=***
>NAME2=***
>NAME3=***
>NAME4=***
>の場合、"NAME1\0NAME2\0NAME3\0NAME4\0\0"が格納されます。

この場合、キー名でなくキー値を同じように格納することは可能でしょうか?

>>Blue様
>> キー名は入力により5・6と増加したり減少したりします。
>どこかに、キーがいくつあるかの情報を保持するようなキーを設定したほうがよさそう
>です。

確かにそうした方が楽な気はするのですが、そうする予定はどうもなさそうですが…
とりあえず提案してみます。

>一応過去ログにこんなのあった

それは一度見たのですが、あまりパッと来ない(単に自分のレベルが低いだけ)
で失礼ですが改めて質問させてもらいました。


>>三草様
>INIファイルにキー(lpKeyName)が見つからなかった場合、
>lpReturnedStringには、lpDefaultの文字列が格納されます。
>なので、KING・王さんの案に追加で、lpDefaultで取得し得ない決めの文字列
>("ENDDATA"とか)を指定しておき、lpReturnedStringがその文字列ならループ(?)を抜け
>る。

確かにそれなら取得できなかった=データがなかった→読み込み処理終了となりますね。
いい案をありがとうございます。


>>PART様
>\0 で区切れば、"NAME1=AAA" が取得できて、
>これを最初の = で区切れば、"NAME1" と "AAA" が取得できます。

GetPrivateProfileSection() は難しそうな気がしたのですがそうではないようですね。
区切るというのはいかようにして実現できるのでしょうか?
ただ、メモリはあまり使いたくない、また、今回ではキー名は必要ないようと今のところ
思っているので今回の場合では使わなくても大丈夫かもしれないです。
ただ、キー名が必要になってくるとおそらくこちらの方がいいみたいですね。

KING・王 2006/07/21(金) 12:54:38
> どう保持した方が後々楽でしょうか?
MFCならCStringArrayを1個ローカル以外に用意するのが、簡単な気がしますが。

> この場合、キー名でなくキー値を同じように格納することは可能でしょうか?
キー値が欲しい場合は、RAPTさんの示されたGetPrivateProfileSection() を用いるのが簡単
だと思います。

>区切るというのはいかようにして実現できるのでしょうか?
GetPrivateProfileSection() で取得したデータがDataに格納されていて、そのサイズがsize
の場合、
例えば、下記のようにすれば区切れます。

for( i=0; i<size; i++ ){
    if( Data[i] == '=' ){ // この'='以降'\0'まではキー値
        i++;
        bFindFlag = false; // キー値格納済みフラグの初期化
        memset( KeyValue, 0x00, sizeof(KeyValue) ); // キー値格納用メモリの初期化
        for( j=0; i<size; i++, j++ ){
            KeyValue[j] = Data[i];
            if( Data[i] == '\0'){ // キー値の末尾までコピー済み
                bFindFlag = true; // キー値格納済みフラグON
                break;
            }
        }
        if( bFindFlag ){
            // KeyValueにキー値が格納されている。
       // CStringArrayObj.Add( KeyValue );
        }
    }
}

さくちゃ 2006/07/21(金) 14:20:15
KING・王 様ご丁寧にありがとうございます。
サンプルでお教えもらったソースを試してみたいと思います。

>> どう保持した方が後々楽でしょうか?
> MFCならCStringArrayを1個ローカル以外に用意するのが、簡単な気がしますが。

それは方法として.hにCstringArrayを追加すると解釈してよろしいのでしょうか?
例 〜.h
CStringArray dataList;

〜.cpp
dataList.Add( KeyValue );

のような感じなのでしょうか?
それはまだ使ったことがないので自分でも調べてみますが、よろしければどうかお願いし
ます。

subaru 2006/07/21(金) 14:47:14
キーと値をセットで保持したいならCMapStringToStringの
方が便利かと(使い方にもよるのでしょうが)
キーのNAMEの部分が固定なら、Blueさんの方法が
スマートだと思いますけど。

Blue 2006/07/21(金) 16:38:15
>メモリはあまり使いたくない
一時的なメモリすら使いたくないのであるならば、
~~~~~~~~
(一時的なメモリサイズはたがかINIファイルサイズ+α)

やはり
三草さんの 2006/07/20(木) 18:42:18 のような取得方法しかないでしょう。
(私の FILENUM がだめな場合)


> CMapStringToString
キーの形式が決まっている(FILE+数字 で欠番のない昇順)のであるならば、
CStringArrayでも十分でしょうね。


> のような感じなのでしょうか?
取得したデータの持ちようによるんじゃないでしょうか?
回答者側からしてみれば、そういう情報(INIファイルの情報をどう使うか)が一切かかれ
ていない以上、具体的なアドバイスはできないと思います。
(メンバ変数にすべきか、ローカル変数にすべきか、CXXXAppのメンバ変数にすべきか)


いまさらですが、環境はきちんと明記しましょう。
OS,VCのバージョン,プロジェクトの種類ぐらいはないと。

例)WindowsXp Pro SP2/Visual C++6.0 Enter SP6/MFC Application ダイアログ

さくちゃ 2006/07/21(金) 17:43:28
subaru様
>キーと値をセットで保持したいならCMapStringToStringの
>方が便利かと(使い方にもよるのでしょうが)
>キーのNAMEの部分が固定なら、Blueさんの方法が
>スマートだと思いますけど。

そうですか。改めて考えようと思います。ありがとうございます。
しかし、CMapStringToStringではキーも保持するようですね。今回はキーは保持しなくても
よいのですが、初めて見ましたのでよく調べてみたいと思います。

Blue様
>いまさらですが、環境はきちんと明記しましょう。
>OS,VCのバージョン,プロジェクトの種類ぐらいはないと。

確かにそうでした。聞かれる立場としてはそれはあって当たり前ですね。申し訳ございま
せんでした。
WindowsXp Pro SP2/VC++7.1/MFCアプリケーション ダイアログです。

>メモリはあまり使いたくない
>一時的なメモリすら使いたくないのであるならば、
>~~~~~~~~
>(一時的なメモリサイズはたがかINIファイルサイズ+α)
>やはり
>三草さんの 2006/07/20(木) 18:42:18 のような取得方法しかないでしょう。
>(私の FILENUM がだめな場合)

以前メモリの関係で大変なことになったのですこしメモリと聞いただけで「えっ?!」と
なってしまいます(苦笑
ですが、今回の場合はそんなに大きくもないですし、よいとは思いますが。。改めて考え
ようと思います。

>取得したデータの持ちようによるんじゃないでしょうか?
>回答者側からしてみれば、そういう情報(INIファイルの情報をどう使うか)が一切かかれ
>ていない以上、具体的なアドバイスはできないと思います。
>(メンバ変数にすべきか、ローカル変数にすべきか、CXXXAppのメンバ変数にすべきか)

確かにこれも仰るとおりです。すいませんでした。
今回はiniからデータを抜き取りそれをコンボボックスのリストに表示させようと考えて
います。
iniはユーザーが扱えるようになるので項目が増えたり減ったり、またはNAMEの名前が変
わることも予想されます。
そのためにiniからのデータの取得はKING・王様が教えてくださった方法を試して、
ローカルのCStringArrayを用意して取得することが出来ました。

ですが、ローカルなので改めて別のメンバ変数に移しなおさないといけないと思います。
出来ればヘッダに別のiniから取得したデータを保持する構造体があるのでその中に加え
て追加したいと思っているのですが今はそこが上手くいっていません。
作りとしては色々とデータを小分けした構造体が複数ありその構造体を一つの構造体でま
とめているような作りです。

typedef struct {
    char szFilter[SIZE_FILTER];
} FILTER_DATA;

typedef struct {
    /*
     ここに他の構造体
    */
    FILTER_DATA        filterData;
} SETTING_DATA;
ととりあえず作ってみました。
このszFilterにCStringArrayで保持しているデータをコピーしたいのですが上手くいきま
せん。
型が違うから上手くいかないのでしょうか?

三草 2006/07/21(金) 18:56:09
Iniからの取得方法は一段落した(?)ようなので、
別の質問であれば一度閉じて、別スレッドを立ててはいかがでしょう。
表題と内容が異なるものになってしまいます。

さくちゃ 2006/07/24(月) 09:21:50
[[解決]]
遅くなり申し訳ございません。

>別の質問であれば一度閉じて、別スレッドを立ててはいかがでしょう。
>表題と内容が異なるものになってしまいます。

そうですね。また分からないことがありましたら、どうか宜しくお願いします。

古いスレッドには追加発言できません。