テキストファイルの上書きをしたいと思ってます。
CStdioFileクラスを使っているのですが、
既存ファイルが100行の場合にWriteStringで
50行書いて終了した場合、既存ファイルの50行が残ります。
コレを消すためにOpen直後にSetLength(0)で長さを強制的に0に
してから書き始めたら、残りはキレイさっぱり消えて、
実際に書き込んだ長さでファイルが保存されました。
ですが、この方法って一般的なのでしょうか?
また、書き込んでいる最中にエラーが発生した場合、
既存ファイルはどうなってしまうのでしょうか?
Close()しなければ元のままと推測してますが。
宜しくお願い致します。
VC6++/Win2Kです。
MSDNより
CFile::CFile(またはCFile::Open)のnOpenFlagsに指定する値
(派生クラスであるCStdioFileも同様)
CFile::modeCreate コンストラクタに新しいファイルを作るように指示します。
ファイルが既に存在するときは、ファイルの内容が切り捨て
られ長さが 0 になります。
とあります。
> 既存ファイルが100行の場合にWriteStringで
> 50行書いて終了した場合、既存ファイルの50行が残ります。
ファイルを開くとき、フラグに modeCreate 使えばいいんじゃない?
> また、書き込んでいる最中にエラーが発生した場合、
> 既存ファイルはどうなってしまうのでしょうか?
> Close()しなければ元のままと推測してますが。
保証はないと思う。
不安なら、一時ファイルに書き出して、Close してから既存ファイルに上書きコピーす
べし。
こちらの質問に答えてなかった。
> また、書き込んでいる最中にエラーが発生した場合、
> 既存ファイルはどうなってしまうのでしょうか?
> Close()しなければ元のままと推測してますが。
ファイルをフラッシュするタイミングによるかと。
modeCreateを指定して開くと、開けた瞬間に全部消えちゃうけど。
CStdioFileを使っている場合に書き込み中の内容が実ファイルに反映されるかどうかは
内部のバッファのサイズと書き込みサイズの大きさによると思います。
内部バッファを越える内容が書き込まれた場合、その時点で内容はファイルに反映されると
思います。ですからCloseしなかったからといって必ずしも元のままというわけには
行かないと思いますよ。
元のファイルを残しておきたいのであれば、書き込み前に元のファイルをリネームして
バックアップファイルとして取っておき、書き込み終了後にファイルを削除するとか、
書き込みを行うファイルは別名称で書き込んでおいてうまく行ったら、元のファイルを
消して、書き込んだファイルをリネームするとかしないとだめでしょう。
元のファイルの内容を残す必要が無いのであれば、
Openする時のフラグをCFile::modeCreateにするのが一般的でしょう。
但し、ファイル内容は一度全てメモリ内に読んでいて書き込み時は最初から最後まで
書き込むようにしている必要があります。必要な部分だけ上書きするような処理だと
上記のフラグだとファイルが消えてしまうのでだめですよ。
皆さん回答有難うございます。
modeCreateで開く案が多数ですが、コレで処理すると、
ファイルの「作成日付」が更新されてしまいますよね?
あくまでも自分の拘りなんですけど「既存のファイルに上書きする」
って事なので、作成日付が更新されてしまうのは・・・。
ちょっと確認してみましたが、秀丸なんかは上書きでも作成日付更新
されないですよね。
私のやり方は一般的じゃない事はわかりました。それで追加で質問なんですが、
SetLength()を使う方法は「間違って」はいないんでしょうか?
この使い方以外にの使い道が思いつきません・・・。
別段問題なければ、コレで行こうと思ってます。
エラーの件は了解しました。参考までに聞きたかったので。
数Kバイトのテキストをちょっといじるのに、バグ以外で
エラーが出るとも思えないし別段バックアップも必要ないので
手抜きします(苦笑)
> ファイルの「作成日付」が更新されてしまいますよね?
やってみましたか?変更されるのは更新日時だとおもうのですが。
見るところ間違えてました。お恥ずかしい限りです(--ゞ
確かに問題ありませんでしたね。
皆さんの仰る通りにmodeCreateでやろうと思います。
SetLength()の方は回答つかなそうですね。
みんな使うこと無いんでしょうかね・・・。
解決とします。ありがとうございました。
> SetLength()の方は回答つかなそうですね。
対して問題はないと思うのですが、
MFCのCFileのWin32APIの使われ方からいくと、
OpenしてからSetLengthすると、CreateFileよんで、SetEndOfFileを呼ぶことになりま
す。
一方Open時にmodeCreateを指定すると、CreateFileを呼ぶだけで終わりです。
となると、SetLengthはなんか無駄がおおそうです。
# 内部でどう処理しているかわからないけど、客観的(?)に見るとね。。。