CFile file;
BOOL ret = file.Open(_T("test.txt"), CFile::modeCreate | CFile::modeWrite);
// 文件已存在時:Open 成功返回 TRUE,但內容被截斷 (覆蓋)!
// 需求:文件存在 → 返回 FALSE,不修改文件。
CFile::modeCreate 語義:**若無則創建,若有則打開並截斷 (truncate)**。fopen("w") / open(O_CREAT | O_TRUNC) 行為。O_EXCL 效果)。CString path = _T("test.txt");
if (PathFileExists(path)) { // 需 #include 並鏈接 Shlwapi.lib
AfxMessageBox(_T("文件已存在!"));
return FALSE;
}
CFile file;
if (!file.Open(path, CFile::modeCreate | CFile::modeWrite)) {
return FALSE;
}
// 寫入數據...
file.Close();
return TRUE;
CFile::modeNoTruncate 組合 (不截斷,但指針在末尾)// modeCreate | modeNoTruncate | modeWrite
// 文件不存在 → 創建
// 文件存在 → 打開,指針在文件末尾,寫入會追加
// 缺點:無法直接實現「存在即失敗」
CreateFile 精確控制HANDLE hFile = CreateFile(
path,
GENERIC_WRITE,
0, NULL,
CREATE_NEW, // 關鍵:CREATE_NEW = 僅創建,存在失敗 (ERROR_FILE_EXISTS)
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_EXISTS) {
// 文件已存在
}
return FALSE;
}
// 寫入...
CloseHandle(hFile);
✅ 精確實現「原子性創建或失敗」,無競態條件。
class CMyFile : public CFile {
public:
BOOL OpenExclusive(LPCTSTR lpszFileName) {
// 內部調用 CreateFile CREATE_NEW
}
};
| 場景 | 推薦方法 |
|---|---|
| 一般業務邏輯,單線程 | 方案一 PathFileExists + CFile::Open |
| 高併發、多進程搶佔創建 | 方案三 CreateFile(CREATE_NEW) 原子操作 |
| 需追加寫入而非覆蓋 | modeCreate | modeNoTruncate | modeWrite |
CFile::Open 無原生「僅創建不覆蓋」標志。**單線程用 PathFileExists 預檢最簡單**;**多線程/進程必須用 Win32 CreateFile(CREATE_NEW) 保證原子性**。