| 屬性 | 說明 | API 存取 |
| 檔名 | cFileName / cAlternateFileName | FindFirstFile |
| 屬性旗標 | FILE_ATTRIBUTE_READONLY/HIDDEN/SYSTEM/ARCHIVE... | GetFileAttributes / SetFileAttributes |
| 建立時間 | FILETIME (UTC, 100ns 間隔, 從 1601/1/1) | GetFileTime / SetFileTime |
| 最後存取時間 | 同上 | 同上 |
| 最後寫入時間 | 同上 | 同上 |
| 檔案大小 | nFileSizeHigh/Low (64-bit) | FindFirstFile / GetFileSizeEx |
核心 API 組合
FindFirstFile / FindNextFile / FindClose:列舉並讀取屬性到 WIN32_FIND_DATA
GetFileAttributes / SetFileAttributes:直接讀寫屬性旗標
CreateFile (GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE):取得檔案句柄
GetFileTime / SetFileTime:精確讀寫三個時間戳 (需檔案句柄)
SystemTimeToFileTime / LocalFileTimeToFileTime:時間格式轉換
自訂屬性結構:方便暫存與複製
typedef struct _FILE_INFO {
TCHAR szFileName[MAX_PATH];
DWORD dwAttributes;
FILETIME ftCreationTime;
ftLastAccessTime;
ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
} FILE_INFO, *PFILE_INFO;
完整實作:複製檔案 A 所有屬性到檔案 B
BOOL CopyFileAttributes(LPCTSTR srcPath, LPCTSTR dstPath) {
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile(srcPath, &findData);
if (hFind == INVALID_HANDLE_VALUE) return FALSE;
FindClose(hFind);
FILE_INFO info = {0};
_tcscpy(info.szFileName, findData.cFileName);
info.dwAttributes = findData.dwFileAttributes;
info.ftCreationTime = findData.ftCreationTime;
info.ftLastAccessTime = findData.ftLastAccessTime;
info.ftLastWriteTime = findData.ftLastWriteTime;
info.nFileSizeHigh = findData.nFileSizeHigh;
info.nFileSizeLow = findData.nFileSizeLow;
// 1. 設定屬性旗標 (唯讀/隱藏/系統/封存...)
if (!SetFileAttributes(dstPath, info.dwAttributes))
return FALSE;
// 2. 設定時間戳 (需開啟檔案取得句柄)
CFile dstFile;
if (!dstFile.Open(dstPath, CFile::modeReadWrite | CFile::shareDenyNone))
return FALSE;
if (!SetFileTime((HANDLE)dstFile.m_hFile,
&info.ftCreationTime,
&info.ftLastAccessTime,
&info.ftLastWriteTime)) {
dstFile.Close();
return FALSE;
}
dstFile.Close();
return TRUE;
}
MFC 對話式專案測試
- 建立 Dialog-based 專案
FileAttr
- 專案目錄放置
1.doc (來源)、2.doc (目標)
- 按鈕
IDC_BTN_COPY_ATTR 處理:
void CFileAttrDlg::OnBtnCopyAttr() {
if (CopyFileAttributes(_T("1.doc"), _T("2.doc"))) {
AfxMessageBox(_T("屬性複製成功!"));
} else {
AfxMessageBox(_T("失敗,請檢查檔案是否存在/權限"));
}
}
時間格式轉換實用函數
// CTime → FILETIME (本地時間)
void CTimeToFileTime(const CTime& ct, FILETIME& ft) {
SYSTEMTIME st;
ct.GetAsSystemTime(st);
SystemTimeToFileTime(&st, &ft);
LocalFileTimeToFileTime(&ft, &ft); // 本地 → UTC
}
// FILETIME → CTime (本地時間)
CTime FileTimeToCTime(const FILETIME& ft) {
FILETIME localFt;
FileTimeToLocalFileTime(&ft, &localFt);
SYSTEMTIME st;
FileTimeToSystemTime(&localFt, &st);
return CTime(st);
}
應用場景
- 備份/同步工具:保留原始時間戳與屬性
- 防毒/安全軟體:掃描後還原時間戳,避免觸發備份軟體重複備份
- 版本控制/建置系統:修正編譯輸出檔案時間,確保增量建置正確
- 數位取證:標準化時間戳格式 (UTC) 進行跨時區分析
- 檔案傳輸驗證:傳輸前後比對屬性確保完整性
注意事項
| 項目 | 說明 |
| 權限需求 | 修改時間需 FILE_WRITE_ATTRIBUTES 權限,通常需管理員或檔案擁有者 |
| FAT32 限制 | 時間解析度僅 2 秒,寫入會四捨五入 |
| 壓縮/加密檔案 | 屬性旗標含 FILE_ATTRIBUTE_COMPRESSED/ENCRYPTED,不可手動設定 |
| 目錄時間 | 目錄同樣支援三個時間戳,API 用法相同 |
| 遞迴處理 | 資料夾樹需配合 FindFirstFile 遞迴,注意 FILE_ATTRIBUTE_DIRECTORY 判斷 |
掌握 WIN32_FIND_DATA + SetFileTime/SetFileAttributes 組合,即可完全掌控檔案系統屬性,滿足企業級應用的嚴格需求。
- 上一篇文章: VC++ 實現檔案移至回收站而非永久刪除:SHFileOperation 完整指南
- 下一篇文章: VC++ 檔案操作全解析:Win32 API (CreateFile) 與 MFC CFile 類對比實戰
Copyright ©
程式碼之家 All Rights Reserved