• ベストアンサー

iniファイルとの比較(iniファイル操作)

 初めまして私はVB6.0の初心者でVB6.0について勉強しています。現在以下のようなiniファイル操作について分からないことがあります。 ・プログラム内容 テキストボックスにログインID(例えばenshu)を入力しOKボタンを押して、iniファイル(例えばrenshu.ini)にある情報と照合してもしiniファイルに無かったら「ログインできません」というメッセージボックスを出すプログラム。 条件 ・ フォームにテキストボックス(Text1.Text)とコマンドボタン(OKボタン)がある ・ Iniファイルの形式(renshu.ini) IDNO(セクション名) OK_ID(キー名)1 = “enshu”(ログインID) OK_ID(キー名)2 = “ren”(ログインID) OK_ID(キー名)3 = “shu”(ログインID) 上のような形式が不特定多数ある ・ Iniファイルの保存場所 c:\work\renshu.ini 私の場合以下のように書きました。 Private Sub OK_Click() 'OKボタンがクリックされたら If  Text1.Text <> GetIniString("IDNO", "OK_ID", "c:\work\renshu.ini") Then '入力したログインIDがiniファイルに無い場合 'メッセージ表示 MsgBox "ログインできません" End If End Sub としましたがメッセージボックスが表示されません。なぜなのでしょうか。教えてください。宜しくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.7

もし、何人だろうが挙げられている方法で処理するなら、例えば… Dim i as Integer 'カウンタ Dim tmpID as String 'IDテンポラリ Dim idExists as Boolean 'ID存在フラグ idExist = False 'ID未発見状態に i = 0 'カウンタ初期化 Do  i = i + 1  tmpID = GetIniString("IDNO", "OK_ID" & CStr(i), "c:\work\renshu.ini")  'Iniにキー値が存在しなかった場合はGetIniStringの戻りが""になるとして、  'その場合は処理終了とする  If tmpID = "" Then Exit Do  '入力がIniのIDにヒットしたらフラグを立ててループから抜ける  If Text1.Text = tmpID Then   idExists = True   Exit Do  End If Loop 'ループ後にIDが未発見ならメッセージ出力 If Not idExists Then  MsgBox "ログインできません" End If …こんな感じので どうでしょ? テストはしてませんが… これの前提条件として、OK_IDn の n は、必ず1から連番で存在しなければいけません。 (抜け番号は存在してはならない) また、必ずログインIDは1文字以上登録されていなければいけません。 (抹消とかの対応のために、IDとして使用不可な文字を決めておいて、  その文字を抜け番の判定に使う、なんて方法も考えられますが) あと、上のソースではインデントに全角Space使ってますので変換してください。 でも…あまり多くなるようでしたら、やっぱりDBの使用をお勧めしますね。 管理大変ですし。

paramia
質問者

お礼

 K-Sogacchiさん、ご回答ありがとうございます。 あと確認の意味で、質問があります。宜しくお願いします。 >Dim i as Integer 'カウンタ このカウンタとはOK_IDn のnをさしているのでしょうか。 >Dim tmpID as String 'IDテンポラリ このIDテンポラリとはどういうことでしょうか。テキストボックスに入力したIDが一時的に保存状態になっているということでしょうか。 >idExist = False 'ID未発見状態に これは、入力したIDがiniファイルに無かった場合という考え方で合っているでしょうか。 初歩的な質問ですみません。

その他の回答 (12)

回答No.13

たびたびすみません、No.7ですが、念のために補足を。 当然ではありますが、No.12のように処理を行う場合、ユーザIDに 「not found」は設定できません(汗)。 厳密に言えば、プログラムの「穴」になりますので、頭の片隅に 入れておいてください。 あと、…何も考えずに答えだけ書いてしまいましたが、なぜ32767まで 止まらずにカウントして、挙句にエラーが出たのか、No.12に書いた内容を 踏まえてコードを読めば判断できるとは思いますので、頑張って考えてみてください。

paramia
質問者

お礼

 色々分かりやすい解説をして頂きありがとうございました。おかげで助かりました。

回答No.12

再びNo.7です。 すみません、最初の方で、見つからなかった際の文字列について言及してたんですね。 んでは、以下の部分は、 'Iniにキー値が存在しなかった場合はGetIniStringの戻りが""になるとして、 If tmpID = "" Then Exit Do 'その場合は処理終了とする End If 以下に変えてください。 'Iniにキー値が存在しなかった場合はGetIniStringの戻りが"not found"になるので、 If tmpID = "not found" Then Exit Do 'その場合は処理終了とする End If …あと、今回の場合はたぶん有り得ないとは思いますが、あまりにIniに登録されている内容が 多くて、32767件を超えていると、同じようなエラーになります。 これは、Integer型が32767までしか対応していないためなので、そういう場合は カウンタや関連する変数をLong型に変更する等の対応が必要になります。 データ型は、細かい事は覚えなくてもいいけど概念だけは理解しないと、 後できっと泥沼にはまりますよ。

回答No.11

No.7です。 >このカウンタとはOK_IDn のnをさしているのでしょうか。 そうです。CStrで文字列にして連結することにより、調べるキー値を設定しています。 >このIDテンポラリとはどういうことでしょうか。テキストボックスに入力したIDが一時的に保存状態になっているということでしょうか。 いえ、そうではありません。 GetIniStringで取得した文字列を、ループ中の 後の処理で複数回使用するので、 わざわざGetIniStringを複数回発行しないよう、1回発行したらその結果を 憶えておくためのテンポラリです。 この辺は、ソースの「書き方」レベルの話ですね。人によって多少書き方は 変わる可能性がありますが… >これは、入力したIDがiniファイルに無かった場合という考え方で合っているでしょうか。 いえ、該当行での処理は、そうではありません。 該当行では、Iniにあったかどうかを憶えておくための、ON・OFFのスイッチ (一般的に「フラグ」という呼び方をすることが多いです)を、初期状態として、 まずOFFに(BooleanなのでFalseに)しています。 で、ループ中にIni内で発見されればスイッチをON(True)にしてループを抜け、 ループ中に発見されないまま終了条件(If tmpID = "" Then Exit Do の部分)に達したら スイッチがONにならない(Falseのまま)でループを抜けるわけです。 この手の処理方法は、私の中では常套手段なんですが… たぶん慣れれば分かりやすいと思いますよ。

paramia
質問者

お礼

ご回答ありがとうございます。 あともう一つ質問があります。 下のプログラムを実行しました。具体的にはテキストボックスにIniに無いID(例えばabcd)を入力して実行させたら「実行時エラー'6':オーバーフローしました」という警告表示が出て、デバッグするとi=i+1の行が黄色になってしまいその行にカーソルを合わせると「i = 32767」と出ます。一体何が原因なのでしょうか。お知恵をお貸しください。宜しくお願いします。 Private Sub Command1_Click() Dim i As Integer 'カウンタ Dim tmpID As String 'IDテンポラリ Dim idExists As Boolean 'ID存在フラグ idExists = False 'ID未発見状態に i = 0 'ID初期化 Do i = i + 1 tmpID = GetIniString("IDNO", "OK_ID" & CStr(i), "c:\work\renshu.ini") 'Iniにキー値が存在しなかった場合はGetIniStringの戻りが""になるとして、 If tmpID = "" Then Exit Do 'その場合は処理終了とする End If If Text1.Text = tmpID Then '入力がIniのIDにヒットしたらフラグを立ててループから抜ける idExists = True Exit Do End If Loop If Not idExists Then 'ループ後にIDが未発見ならメッセージ出力 MsgBox "ログインできません" End If End Sub

回答No.10

確かに、redfox63氏の指摘通り、私の書いたやり方は、特に行数が多くなると レスポンスが悪くなるはずです。1000とか超えると現実的じゃないレスポンスに なるかも… 理由は、(あくまで推測ですが)GetPrivateProfileStringが、内部的に 「単純に先頭からLine Inputで1行ずつ読みながら文字列検索する」という動作を していると仮定すると、以下の形のIniだと… [IDNO] OK_ID1=xxx OK_ID2=xxx  :  : OK_ID100=xxx …OK_ID1を見つけるのに、2行読む事になります。 OK_ID2だと3行です。OK_ID100は101行です。 となると、100行あったら、読むのは100行じゃなくて 2+3+4+……+101 行になります。 おまけに、GetPrivateProfileStringを発行するごとに、ファイルのOpen、Closeも 行っているはずですので、更に遅くなります。 GetPrivateProfileSection(これの存在は初めて聞きました…)で一気に取得するか、 Iniファイルといえど結局は基本的にただのテキストファイルなので、 自力で読みながら文字列解析するか、の方が、あくまでIniファイルを 使用するならば現実的なのかもしれません。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.9

K-Sogacchi氏の回答のように、Iniファイルをなめてやれば 1000人だろうと2000人だろうと可能です ただ、レスポンスが悪くなったり無駄が多いのでより効率的に認証させたいならと思い#6の回答内容となります 毎回 GetPrivateProfileStringで検索するより GetPrivateProfileSectionでセクションごとデータを取得して 改行などで配列に分割、この配列を検索する といった手法もあるでしょう

回答No.8

NO.7です。すみません、バグがありました(汗) idExist = False 'ID未発見状態に ではなく、 idExists = False 'ID未発見状態に ですね。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.6

一般的な話をすれば 100人とか照合しないといけないのであれば 照合用のIDとパスワードといった組み合わせで入力をさせるようにします そうすれば GetIniStringの現在キーにしている ID_OKxxといった物が不要になります つまりIDとして入力される "enshu"、"ren"、"shu"などをキーにして データのパスワードをGetIniStringで引き出すといった具合にします もっと管理する人数が増えるのであれば データベースを使うように考えましょう

paramia
質問者

お礼

ご回答頂きありがとうございます。  それではテキストボックスに入力したIDデータ1つとiniファイルにあるIDデータ全部(IDデータの数が10未満でもよい)を比較することは不可能なのでしょうか。お知恵をお貸しください。宜しくお願いします。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.5

> GetIniStringで取得したデータとText1.Textは同一ではありませんでした。 > 一体何が原因なのでしょうか。 単に『同一ではありませんでした』といわれても原因なんて分かりません WinAPIのGetPrivateProfileStringでエラーになったのか、その他のロジックが悪いのか 実行した結果ssが『何々』でしたとか lngRetの値が『云々』でしたといった返答をしましょう # われわれ回答者はあなたのすぐそばで見ているわけではありません 他の方も回等しているように GetIniStringの引数garKeyの与え方がまずいため返り値が"not found"になっているのであろうと思います garKeyに "OK_ID1"、"OK_ID2"、"OK_ID3"などを与えて検査するようにしましょう

paramia
質問者

お礼

ご回答ありがとうございます。 Private Sub Command1_Click() Dim ID As String 'iniファイルから文字列を取得する関数 ID = GetIniString-("IDNO", "OK_ID4", "c:\work\renshu.ini") '関数を変数IDに格納----★ If Text1.Text <> ID Then MsgBox "ログインできません" End If End Sub >garKeyに "OK_ID1"、"OK_ID2"、"OK_ID3"などを与えて検査するようにしましょう GetIniString("IDNO", "OK_ID4", "c:\work\renshu.ini") のキー名の部分を"OK_ID1"、"OK_ID2"、"OK_ID3"という風に変更してテキストボックスに★と違うログインIDを入力した結果「ログインできません」とでました。ただGetIniString関数で取得できるデータはひとつだけで、iniファイルにあるログインIDが不特定多数(例えばiniファイルにログインIDが100個ある場合)と照合するときには不向きです。こういう場合GetIniStringの引数のキー名の部分をどのように表せばよいのでしょうか。ご教授ください。宜しくお願いします。

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.4

前にも書いたんだけど、 GetIniString("IDNO", "OK_ID", "c:\work\renshu.ini")      ↓ GetIniString("IDNO", "OK_ID1", "c:\work\renshu.ini") GetIniString("IDNO", "OK_ID2", "c:\work\renshu.ini") GetIniString("IDNO", "OK_ID3", "c:\work\renshu.ini") なのでは? "OK_ID"≠"OK_ID1"ですから… それと、OK_ID1="AAA"のように記述すると、"も入ってしまうのでは? いきなり比較しないで、他の方の回答のようにイミディエイトウィンドウに表示してみましょう。 Dim ID As String ID = GetIniString("IDNO", "OK_ID", "c:\work\renshu.ini") Debug.Print ID If Text1.Text <> ID Then ・・・・

  • _backyarD
  • ベストアンサー率34% (199/580)
回答No.3

手元にVB6.0なんて無いので、とりあえず... VB6.0に限らず、Visual Studio系の開発環境はデバッグモードでの動作が可能です。ソースコードの、If文の所の左端をクリックすると行が小豆色になると思うので、そのままデバッグモードで実行してみましょう。 そうすると、その行で処理が止まります(行が黄色くなるハズ)。その状態で「Text1.Text」など、変数にカーソルを合わせると、その内容が浮き出て表示されるので、実際にどういう値や文字列が入っているかを見ることが出来ます。 また、その状態で「Ctrl+G」とかを押すと、イミディエイトウィンドウというウィンドウが開きます。ここでは、その場で命令を実行させたりできます。 そこで、 ?GetIniString("IDNO", "OK_ID", "c:\work\renshu.ini") のように、先頭に「?」を付けて関数や変数を打ち込んでみてください。その内容が表示されます。なので、たとえばここで直接GetIniStringの中身をいろいろ変えながら試して、実際に何が返ってきているかということを調べる事が出来ます。 また、先頭に「?」を付けずに、 Text1.Text="あいうえお" などと打つと、その変数やプロパティに値をいれる(内容を変える)ことも可能です。 こういうツールをうまく使いこなして、まずは自分で解決をはかりましょう。

paramia
質問者

補足

ご回答ありがとうございます。 >VB6.0に限らず、Visual Studio系の開発環境はデバッグモードでの動作が可能です デバッグモードで実行というのは具体的にはどうすればよいのでしょうか。If文の所の左端をクリックして行が小豆色になった後実行ボタンを押せばよいのでしょうか。教えてください。宜しくお願いします。

関連するQ&A