テキストファイルをOPENして、最終行まで読み込んで、CLOSEするという
処理を『同じファイル』に対して何回も行いたいのですが、
上手くいきません。
以下のような関数を何回も呼び出す形なのですが、
二回目になると★印のところでループしないで処理を抜けてしまいます。
------------------------------------------------------------------
Private Function Sumple_Src() As Boolean
〜変数定義省略〜
l_intFileNo = FreeFile
l_strFileName = "AAA.txt"
Open l_strFileName For Input As l_intFileNo
Do While Not EOF(l_intFileNo) ←★
l_strData = l_strData & Input(1, l_intFileNo)
Loop
Close l_intFileNo
〜省略〜
End Function
------------------------------------------------------------------
一回目にこの関数を呼び出すときは
ちゃんと最終行まで読み込めるのですが、
二回目にこの関数をよびだすと、★印のところで一回だけループして
抜けてしまいます。
二回目になると読込位置が既にEOFになっているような感じです。
ファイルを一旦クローズしても、「最終行まで読み込んだ」という
情報がメモリとかどっかに残っているということなのでしょうか?
理由が分からず困っています。
また、ならば読込位置を一旦ファイルの先頭に戻すという処理を
入れてあげればいいのかと考えましたが、どういうソースを書けば
いいのか、わからない状態です。
どなたか教えていただけないでしょうか
よろしくお願いします。
同じコードで試してみましたが、ちゃんと何回やっても全て読み取るようですね。
残念ながらこちらの環境(WinXP SP2, VB6 SP6)再現しませんでした。
ただ、読み取るデータが提示されてませんでしたので適用に
1
2
3
4
5
6
7
8
9
10
というようなテキストファイル(AAA.txt)を作成してやってみました。
>再現しないね。
一応自分も作ってみたけどさ
Private Function Sample_Src() As Boolean
Next_Proc:
'使用可能なファイル番号を取得
intFileNo = FreeFile
'テキストファイルをオープン
Open "c:\aaa.txt" For Input As #intFileNo
' ファイルの終端までループを繰り返します。
Do While Not EOF(intFileNo)
'1 行づつ変数に読み込みます。
Line Input #intFileNo, strTextLine
MsgBox strTextLine
Loop
'ファイルを閉じる
Close #intFileNo
GoTo Next_Proc:
End Function
無限ループ注意
Booさん、いなさん
試していただいてありがとうございます。
再現しないということで、
余計な時間を取らせてしまいすいませんでした。
私の環境(WinXP SP1、VB6.0)では、事象が発生し続けています。
何が原因なんだろう。。。
ただ、お二人のおかげで関数の中身自体は問題がなさそうということは
分かったので、関数を呼び出している方などを調べてみます。
ありがとうございました。
一応あがいてみようかな。。。
相対パスを絶対パスにしてみる。。。とか(く、苦しい)
l_strFileName = "AAA.txt"
l_strFileName = App.Path & "\AAA.txt"
どこかで、
カレントフォルダ移動している処理があったり、無かったり
> 〜省略〜
呼び出し部も含めて、再現できるコードになっていれば、
検証しやすいのですけれどね。
> 二回目にこの関数をよびだすと、★印のところで一回だけループして
> 抜けてしまいます。
『二回目の呼び出し』時であっても、
(0回ではなく)1回だけはループするのですね?
という事は、『l_strData = l_strData & Input(1, l_intFileNo)』の行は、
一度だけ実行されるのだと思います。ではその時、変数 l_strData の内容は、
この行の実行の前と後とで、期待値通りの値になっているか、確認してみては。
> 二回目になると読込位置が既にEOFになっているような感じです。
実際に、きちんと確認してみましょう。
Seek関数を使えば、現在の読み込み位置がわかりますよ。
Debug.Print "FileNo:"; l_intFileNo, "Position:"; Seek(l_intFileNo)
とりあえず、疑うとすれば……
・Open時に、InputモードとOutputモードを間違えている箇所はありませんか?
(1回目と2回目で、ファイルサイズが変化していたりはしませんか?)
・Option Explicitを宣言してありますか?
(スペルミスが原因で、想定外の動作になっているとか)
・むやみに、モジュールレベル変数を宣言していませんか?
(他のプロシージャで、変数の値をうっかり変えてしまう可能性がある)
・Open前後で、カレントドライブやカレントディレクトリは移動していませんか?
(いなさんが書いたように、フルパスを使った方が安全です)
・Sumple → Sample ではありますまいか。
(どうでも良いことですけど)
>相対パスを絶対パスにしてみる。。。とか(く、苦しい)
早速やってみました。
ファイルの存在確認もできるように以下のような形で
やってみました。
l_strFileName = Dir(App.Path & "AAA.txt")
If l_strFileName = "" Then
'ファイルが無い時の処理
End If
毎回関数が呼ばれる時にちゃんと同じファイルを
OPENできているのですが、事象は解消できませんでした。
この関数以外にファイル操作をしている箇所はないんですが、
原因はわからないままです。
ただ、新規にプロジェクトファイルを作って、
問題の関数のみ抜き出してやってみたら上手くいっちゃいました。
やはり、今作っているプログラムに問題があるみたいで、
関数が大分深いところにあるので、呼び出すタイミングを
いろいろと変えてみたりしているのですが、
まだ原因と思われるものにすらたどりつけていません。
もう少し、頑張ってみてダメであったら、ファイルを複数個
用意して、別の名前にするなどで別の手立てを考えようと思います。
>『二回目の呼び出し』時であっても、
>(0回ではなく)1回だけはループするのですね?
ごめんなさい。
ループはしていませんでした。
ループ0回で処理を抜けています。
>実際に、きちんと確認してみましょう。
>Seek関数を使えば、現在の読み込み位置がわかりますよ。
> Debug.Print "FileNo:"; l_intFileNo, "Position:"; Seek(l_intFileNo)
ありがとうございます。
確認してみました。
ちなみにファイルは固定長のテキストファイルで、
1行80バイトで22行あります。
改行コードを含めて全部で1804バイトのファイルです。
一回目はループするので、処理が終わると
読込位置は1805になっています。
二回目はループしないので、読込位置は1のままでした。
二回目もちゃんと同じファイルをみれているのかが
疑わしくなってきました。
(フルパス指定にしたのですが、何か別の問題があるのかも)
>l_strData = l_strData & Input(1, l_intFileNo)
↑
これはおかしくないかい????
Input #filenumber, varlistだよね。。
> id_rsa+さん
Input()も有りますし、構文としては問題ないように思いますが…?
> ひよこさん
> 新規にプロジェクトファイルを作って、
> 問題の関数のみ抜き出してやってみたら上手くいっちゃいました。
うーん…
名前の競合が起こっているかもしれませんので、
一応[_HiddenModule].Input()にしておいたほうがいいかもしれないですね。
※なんか激しく誤爆かも(orz
原因が分かり解決できました。
以下の二点が原因でした。
①問題の関数のその後の処理で、自分で作ったDLLを呼出していて、
Log出力を行っていた
②Dir関数を誤った認識で使用していた
後続処理で自分で作ったDLLを呼出していて、
そのDLLの中で処理結果をログファイルに出力していました。
この際にカレントディレクトリが、DLLのログファイルの出力先に
移動していました。
また、試行錯誤している中でOPENのモードを変えたりしてやって
いたので、その際にDLLのログファイル出力先に、今回処理したい
ファイルと同じ名前の0バイトファイルが出来上がっていたみたいです。
(これに気付いていませんでした。)
それと、Dir関数について誤った思い込みで使用していました。
Dir関数の結果として返ってくるのは、ファイルまたはフォルダの
名前だけなのですね。
l_strFileName = Dir(App.Path & "AAA.txt")
これで、絶対パス指定できているつもりになっていましたが、
存在確認自体は絶対パスでやっているが、
l_strFileNameに格納されるのは、"AAA.txt"だけで、
絶対パス指定になっていないという状態でした。
処理を順番でいくとこんな感じだったと思います。
①問題の関数実行
(一回目は、期待通りのファイルをみれている。)
↓
②DLL呼出
(カレントディレクトリ移動)
↓
③問題の関数実行
(二回目は、DLLのログ出力先にあった0バイトファイルを
みてしまっている。)
以下のように絶対パス指定で、変数に格納し直したら
上手くいきました。
l_strFileName = Dir(App.Path & "AAA.txt")
If l_strFileName = "" Then
'ファイルが無い時の処理
End If
l_strFileName = App.Path & "AAA.txt" ←★追加
最初は、実現可否について力を借りたいというつもりで
質問したのですが、結局は自分のプログラムのバグでした。
お騒がせしてすいませんでした。
お力添えをいただいた皆様ありがとうございました。
ツイート | ![]() |