プロが教えるわが家の防犯対策術!

CFile::Renameで書き込み途中のファイルがリネームされて困っています。
ファイル書き込み中のファイルはリネームしない方法はあるのでしょうか?

ファイルのリネーム(CFile::Rename)関数を使用してフォルダ内にあるファイル名をリネームする処理を作成しています。
フォルダ内にはA_で始まるファイルが複数存在し、一定周期で別のスレッドからA_で始まるファイルが書き込まれている状態です。

私が作成している処理は、そのフォルダにA_で始まるファイルが存在する場合に、A_をRename関数でB_にリネームしています。

ここで、別スレッドがA_で始まる新しいファイルを書き込みしている最中に私が作成している処理でRename関数が実行されると、基本的にはExceptionが発生するのですが、Exceptionが発生せずに書き込み途中のファイルがRenameされてしまっています。

1.A_XXX001.txtに書き込み中(100行目まで書き込み完了)
2.Rename処理が実行される。
3.B_XXX001.txtが作成される(100行目までのファイル 作成日:2010.02.04 10:00)
4.その後もA_XXX001.txtに書き込みが行われ200行目まで書き込んで終了
(作成日:2010.02.04 10:02)

結果:B_XXX001.txtファイルは不完全なファイルとして作成されてしまっています。
このような現象が起こってしまっています。


どなたかご教授願います。

A 回答 (5件)

もう見てないかもしれませんが・・・


Mutex等で排他制御をする場合、排他にしたい操作全部にロック操作を追加します。今回の場合だとファイル書き込みとファイル名変更ですね。参考ソースがあるのでそこに追記してみました。

CMutex mtxFile; // このオブジェクトをファイル名変更ロジックからもアクセスできるようにしておく

CStdioFile csfCsvFile;
CFileException e = NULL;

CSingleLock lockFile(&mtxFile);
lockFile.Lock();

csfCsvFile.Open(csFullPath,CFile::modeCreate | CFile::modeWrite | CFile::typeText,&e)

try {
pos = NULL;
if ( !csCsvDataList.IsEmpty() ) pos = csCsvDataList.GetHeadPosition();
while ( pos != NULL ) {
CString csCsvRecord;
csCsvRecord = "書き込み内容";

// 1行書込の実行
csfCsvFile.WriteString(csCsvRecord);
csfCsvFile.WriteString(_T("\n"));
}
}
// ファイル書き込み失敗時
catch ( CFileException *e ) {
エラーログ出力
}

lockFile.Unlock();

これと同じようにしてファイル名変更ロジックにLock~Unlockを追加します。
ただし、この場合だと1行書き込んだタイミングでロックが解除されますので、全部書き込むまでロックする場合は、そのロジック全体をLock~Unlockで囲う必要があります。
    • good
    • 0

書き込み側のスレッドで、A_XXX001.TXTのファイル名でいきなり書くのでなく、


TEMP_XXXのようなファイル名で書いて、書き込み完了後、そのスレッドが、A_XXX001.TXTのファイル名にリネームにしてはいかがでしょうか。
(パフォーマンス等は、考慮していません。)
    • good
    • 0

A_XXX001.txtをリネームする前に、中身を確認して、「不完全」だったらリネームしないという方法はどうでしょうか。

    • good
    • 0

ある資源(今回の場合はファイル)に対して複数のスレッドからアクセスするシステムの場合、クリティカルセクションなりセマフォなりを利用して複数のスレッドが同じ資源に同時にアクセスしないようにするのが常識です。


開発環境がわかりませんので、マルチスレッド等のキーワードでググってください。
    • good
    • 0

MutexかEventを使って排他制御するのが一番だと思いますが・・・

この回答への補足

MISTMOON79 さん、RESET_CAT さん ありがとうございます。

現在、排他制御に関して調べているのですが、今回の私の処理の場合、
排他制御を掛けるのはファイル書き込みの部分に当たるのでしょうか?

書き込みをしているファイルを排他制御対象にすることで、そのファイル名を変更するRenameはロックされているファイルはRenameしなくなるのでしょうか?

現在、書き込み処理は以下のようになっています。

Mutexを使用する場合はどのようにしたら、書き込んでいるファイルをロックできるのでしょうか?


CStdioFile csfCsvFile;
CFileException e = NULL;

csfCsvFile.Open(csFullPath,CFile::modeCreate | CFile::modeWrite | CFile::typeText,&e)

try {
pos = NULL;
if ( !csCsvDataList.IsEmpty() ) pos = csCsvDataList.GetHeadPosition();
while ( pos != NULL ) {
CString csCsvRecord;
csCsvRecord = "書き込み内容";

// 1行書込の実行
csfCsvFile.WriteString(csCsvRecord);
csfCsvFile.WriteString(_T("\n"));
}
}
// ファイル書き込み失敗時
catch ( CFileException *e ) {
エラーログ出力
}

補足日時:2010/02/04 14:46
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!