ファイル操作に関して、こんなことできますでしょうか

解決


ひよこ  2005-05-19 20:05:58  No: 121780  IP: [192.*.*.*]

テキストファイルを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になっているような感じです。
ファイルを一旦クローズしても、「最終行まで読み込んだ」という
情報がメモリとかどっかに残っているということなのでしょうか?
理由が分からず困っています。
また、ならば読込位置を一旦ファイルの先頭に戻すという処理を
入れてあげればいいのかと考えましたが、どういうソースを書けば
いいのか、わからない状態です。

どなたか教えていただけないでしょうか
よろしくお願いします。

編集 削除
Boo  2005-05-19 20:41:50  No: 121781  IP: [192.*.*.*]

同じコードで試してみましたが、ちゃんと何回やっても全て読み取るようですね。
残念ながらこちらの環境(WinXP SP2, VB6 SP6)再現しませんでした。
ただ、読み取るデータが提示されてませんでしたので適用に
1
2
3
4
5
6
7
8
9
10
というようなテキストファイル(AAA.txt)を作成してやってみました。

編集 削除
いな  2005-05-19 20:52:35  No: 121782  IP: [192.*.*.*]

>再現しないね。

一応自分も作ってみたけどさ

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

無限ループ注意

編集 削除
ひよこ  2005-05-19 21:30:59  No: 121783  IP: [192.*.*.*]

Booさん、いなさん
試していただいてありがとうございます。

再現しないということで、
余計な時間を取らせてしまいすいませんでした。


私の環境(WinXP SP1、VB6.0)では、事象が発生し続けています。
何が原因なんだろう。。。
ただ、お二人のおかげで関数の中身自体は問題がなさそうということは
分かったので、関数を呼び出している方などを調べてみます。

ありがとうございました。

編集 削除
いな  2005-05-19 22:04:52  No: 121784  IP: [192.*.*.*]

一応あがいてみようかな。。。
相対パスを絶対パスにしてみる。。。とか(く、苦しい)

 l_strFileName = "AAA.txt"

 l_strFileName = App.Path & "\AAA.txt"

どこかで、
カレントフォルダ移動している処理があったり、無かったり

編集 削除
魔界の仮面弁士  2005-05-19 23:17:29  No: 121785  IP: [192.*.*.*]

> 〜省略〜
呼び出し部も含めて、再現できるコードになっていれば、
検証しやすいのですけれどね。


> 二回目にこの関数をよびだすと、★印のところで一回だけループして
> 抜けてしまいます。
『二回目の呼び出し』時であっても、
(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 ではありますまいか。
 (どうでも良いことですけど)

編集 削除
ひよこ  2005-05-19 23:32:40  No: 121786  IP: [192.*.*.*]

>相対パスを絶対パスにしてみる。。。とか(く、苦しい)
早速やってみました。
ファイルの存在確認もできるように以下のような形で
やってみました。

l_strFileName = Dir(App.Path & "AAA.txt")
If l_strFileName = "" Then
   'ファイルが無い時の処理
End If


毎回関数が呼ばれる時にちゃんと同じファイルを
OPENできているのですが、事象は解消できませんでした。
この関数以外にファイル操作をしている箇所はないんですが、
原因はわからないままです。

ただ、新規にプロジェクトファイルを作って、
問題の関数のみ抜き出してやってみたら上手くいっちゃいました。
やはり、今作っているプログラムに問題があるみたいで、
関数が大分深いところにあるので、呼び出すタイミングを
いろいろと変えてみたりしているのですが、
まだ原因と思われるものにすらたどりつけていません。
もう少し、頑張ってみてダメであったら、ファイルを複数個
用意して、別の名前にするなどで別の手立てを考えようと思います。

編集 削除
ひよこ  2005-05-20 00:07:15  No: 121787  IP: [192.*.*.*]

>『二回目の呼び出し』時であっても、
>(0回ではなく)1回だけはループするのですね?
ごめんなさい。
ループはしていませんでした。
ループ0回で処理を抜けています。


>実際に、きちんと確認してみましょう。
>Seek関数を使えば、現在の読み込み位置がわかりますよ。
> Debug.Print "FileNo:"; l_intFileNo, "Position:"; Seek(l_intFileNo)
ありがとうございます。
確認してみました。
ちなみにファイルは固定長のテキストファイルで、
1行80バイトで22行あります。
改行コードを含めて全部で1804バイトのファイルです。

一回目はループするので、処理が終わると
読込位置は1805になっています。
二回目はループしないので、読込位置は1のままでした。
二回目もちゃんと同じファイルをみれているのかが
疑わしくなってきました。
(フルパス指定にしたのですが、何か別の問題があるのかも)

編集 削除
id_rsa+  2005-05-20 02:39:15  No: 121788  IP: [192.*.*.*]

>l_strData = l_strData & Input(1, l_intFileNo)   


これはおかしくないかい????
Input #filenumber, varlistだよね。。

編集 削除
ガッ  2005-05-20 07:24:31  No: 121789  IP: [192.*.*.*]

> id_rsa+さん
Input()も有りますし、構文としては問題ないように思いますが…?

> ひよこさん
> 新規にプロジェクトファイルを作って、
> 問題の関数のみ抜き出してやってみたら上手くいっちゃいました。
うーん…
名前の競合が起こっているかもしれませんので、
一応[_HiddenModule].Input()にしておいたほうがいいかもしれないですね。

※なんか激しく誤爆かも(orz

編集 削除
ひよこ  2005-05-20 13:59:47  No: 121790  IP: [192.*.*.*]

原因が分かり解決できました。

以下の二点が原因でした。
①問題の関数のその後の処理で、自分で作った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"   ←★追加



最初は、実現可否について力を借りたいというつもりで
質問したのですが、結局は自分のプログラムのバグでした。
お騒がせしてすいませんでした。

お力添えをいただいた皆様ありがとうございました。

編集 削除