こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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
としましたがメッセージボックスが表示されません。なぜなのでしょうか。教えてください。宜しくお願いいたします。

投稿日時 - 2008-05-08 17:22:00

QNo.4006997

すぐに回答ほしいです

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

もし、何人だろうが挙げられている方法で処理するなら、例えば…

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の使用をお勧めしますね。
管理大変ですし。

投稿日時 - 2008-05-09 15:01:55

お礼

 K-Sogacchiさん、ご回答ありがとうございます。
あと確認の意味で、質問があります。宜しくお願いします。

>Dim i as Integer 'カウンタ
このカウンタとはOK_IDn のnをさしているのでしょうか。

>Dim tmpID as String 'IDテンポラリ
このIDテンポラリとはどういうことでしょうか。テキストボックスに入力したIDが一時的に保存状態になっているということでしょうか。

>idExist = False 'ID未発見状態に
これは、入力したIDがiniファイルに無かった場合という考え方で合っているでしょうか。

初歩的な質問ですみません。

投稿日時 - 2008-05-12 10:45:39

このQ&Aは役に立ちましたか?

11人が「このQ&Aが役に立った」と投票しています

回答(13)

ANo.13

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

投稿日時 - 2008-05-12 16:35:33

お礼

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

投稿日時 - 2008-05-12 17:03:32

ANo.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型に変更する等の対応が必要になります。
データ型は、細かい事は覚えなくてもいいけど概念だけは理解しないと、
後できっと泥沼にはまりますよ。

投稿日時 - 2008-05-12 16:26:44

ANo.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のまま)でループを抜けるわけです。

この手の処理方法は、私の中では常套手段なんですが… たぶん慣れれば分かりやすいと思いますよ。

投稿日時 - 2008-05-12 11:12:20

お礼

ご回答ありがとうございます。
あともう一つ質問があります。
下のプログラムを実行しました。具体的にはテキストボックスに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

投稿日時 - 2008-05-12 16:13:33

ANo.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ファイルを
使用するならば現実的なのかもしれません。

投稿日時 - 2008-05-09 22:41:45

ANo.9

K-Sogacchi氏の回答のように、Iniファイルをなめてやれば 1000人だろうと2000人だろうと可能です
ただ、レスポンスが悪くなったり無駄が多いのでより効率的に認証させたいならと思い#6の回答内容となります

毎回 GetPrivateProfileStringで検索するより
GetPrivateProfileSectionでセクションごとデータを取得して
改行などで配列に分割、この配列を検索する
といった手法もあるでしょう

投稿日時 - 2008-05-09 17:03:31

ANo.8

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

投稿日時 - 2008-05-09 15:07:23

ANo.6

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

もっと管理する人数が増えるのであれば データベースを使うように考えましょう

投稿日時 - 2008-05-09 14:24:56

お礼

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

投稿日時 - 2008-05-09 15:25:24

ANo.5

> GetIniStringで取得したデータとText1.Textは同一ではありませんでした。
> 一体何が原因なのでしょうか。
単に『同一ではありませんでした』といわれても原因なんて分かりません
WinAPIのGetPrivateProfileStringでエラーになったのか、その他のロジックが悪いのか
実行した結果ssが『何々』でしたとか lngRetの値が『云々』でしたといった返答をしましょう
# われわれ回答者はあなたのすぐそばで見ているわけではありません

他の方も回等しているように
GetIniStringの引数garKeyの与え方がまずいため返り値が"not found"になっているのであろうと思います

garKeyに "OK_ID1"、"OK_ID2"、"OK_ID3"などを与えて検査するようにしましょう

投稿日時 - 2008-05-09 00:27:14

お礼

ご回答ありがとうございます。
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の引数のキー名の部分をどのように表せばよいのでしょうか。ご教授ください。宜しくお願いします。

投稿日時 - 2008-05-09 13:56:23

ANo.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
・・・・

投稿日時 - 2008-05-08 19:16:03

ANo.3

手元にVB6.0なんて無いので、とりあえず...

VB6.0に限らず、Visual Studio系の開発環境はデバッグモードでの動作が可能です。ソースコードの、If文の所の左端をクリックすると行が小豆色になると思うので、そのままデバッグモードで実行してみましょう。

そうすると、その行で処理が止まります(行が黄色くなるハズ)。その状態で「Text1.Text」など、変数にカーソルを合わせると、その内容が浮き出て表示されるので、実際にどういう値や文字列が入っているかを見ることが出来ます。

また、その状態で「Ctrl+G」とかを押すと、イミディエイトウィンドウというウィンドウが開きます。ここでは、その場で命令を実行させたりできます。
そこで、

?GetIniString("IDNO", "OK_ID", "c:\work\renshu.ini")

のように、先頭に「?」を付けて関数や変数を打ち込んでみてください。その内容が表示されます。なので、たとえばここで直接GetIniStringの中身をいろいろ変えながら試して、実際に何が返ってきているかということを調べる事が出来ます。

また、先頭に「?」を付けずに、

Text1.Text="あいうえお"

などと打つと、その変数やプロパティに値をいれる(内容を変える)ことも可能です。

こういうツールをうまく使いこなして、まずは自分で解決をはかりましょう。

投稿日時 - 2008-05-08 18:24:52

補足

ご回答ありがとうございます。

>VB6.0に限らず、Visual Studio系の開発環境はデバッグモードでの動作が可能です

デバッグモードで実行というのは具体的にはどうすればよいのでしょうか。If文の所の左端をクリックして行が小豆色になった後実行ボタンを押せばよいのでしょうか。教えてください。宜しくお願いします。

投稿日時 - 2008-05-09 09:50:55

ANo.2

GetIniStringはDeclare宣言した関数なのでしょうか?
VB6の標準装備の関数ではないと思いますが ・・・

GetIniStringの中身の詳細を投稿しましょう

もし WinAPIの GetPrivateProfileStringを使っているなら
キー名は OK_ID1 などの完全名が必要だろうと思いますよ

本当にGetIniStringで取得したデータと Text1.Textが同一なのかどうかを簡単にチェックするなら
Dim ss as String
ss = GetIniString("IDNO", "OK_ID", "c:\work\renshu.ini")
if Text1.Text <> ss then
といったん変数に代入しておいて比較してみましょう

投稿日時 - 2008-05-08 17:52:17

補足

ご回答ありがとうございます。
以下のような感じでよろしいでしょうか。
>GetIniStringの中身の詳細を投稿しましょう
Public Function GetIniString( _
ByVal garSection As String, _
ByVal garKey As String, _
ByVal garFileName As String _
) As String

Dim llngRet As Long
Dim lstrValue As String * 255

llngRet = GetPrivateProfileString(garSection, garKey, "not found", lstrValue, 255, garFileName)
GetIniString = Left$(lstrValue, InStr(lstrValue, vbNullChar) - 1)

End Function

投稿日時 - 2008-05-08 18:13:31

お礼

続けざまで申し訳ございません。
>本当にGetIniStringで取得したデータと Text1.Textが同一なのかどうかを簡単にチェックするなら
Dim ss as String
ss = GetIniString("IDNO", "OK_ID", "c:\work\renshu.ini")
if Text1.Text <> ss then
といったん変数に代入しておいて比較してみましょう

 試しに上記のようにやってみたら、GetIniStringで取得したデータと Text1.Textは同一ではありませんでした。一体何が原因なのでしょうか。

投稿日時 - 2008-05-08 18:32:57

ANo.1

(1)iniファイルの中身
セクション名は[]で囲みます。質問では裸で記述されているようです。
(2)パラグラフの指定
iniファイルではOK_ID1、OK_ID2、…なのでは?
プログラムからは"OK_ID"としか指定していません。1や2はどうなった?

投稿日時 - 2008-05-08 17:45:31

お礼

ご回答ありがとうございます。
[IDNO](セクション名)

>iniファイルではOK_ID1、OK_ID2、…なのでは?
はいそうです。

OK_ID1(キー名) = “enshu”(ログインID)
OK_ID2(キー名) = “ren”(ログインID)
OK_ID3(キー名) = “shu”(ログインID)
上記のように書きたかったんです。

>1や2はどうなった?
これはOK_ID1とOK_ID2のことを言っているのでしょうか?

投稿日時 - 2008-05-08 18:12:28

あなたにオススメの質問