HOWTO · C++
如何在 C++ 中檢查一個檔案是否存在
本文介紹了檢查目錄下檔案是否存在的幾種方法,C++
本頁內容
使用 std::filesystem::exists 檢查路徑是否指向現存的檔案系統項目。檔案和目錄都會回傳 true。下方範例會建立一個小型暫存目錄和檔案,讓檢查有可獨立使用的輸入;請將 file 替換成程式需要檢查的路徑。
使用 std::filesystem::exists 檢查檔案是否存在於目錄中
執行以下範例:
#include <chrono>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
int main() {
namespace fs = std::filesystem;
const auto unique = std::chrono::steady_clock::now().time_since_epoch().count();
const fs::path folder = fs::temp_directory_path() /
("cpp-exists-" + std::to_string(unique));
std::error_code ec;
if (!fs::create_directory(folder, ec) || ec) {
std::cout << "Could not prepare example\n";
return 1;
}
struct cleanup_guard {
fs::path path;
~cleanup_guard() {
std::error_code cleanup_error;
fs::remove_all(path, cleanup_error);
}
} cleanup{folder};
const fs::path file = folder / "notes.txt";
{
std::ofstream output(file);
if (!output) {
std::cout << "Could not prepare example\n";
return 1;
}
}
std::cout << (fs::exists(file) ? "Path exists\n" : "Path does not exist\n");
std::cout << (fs::is_regular_file(file) ? "It is a regular file\n"
: "It is not a regular file\n");
}
Path exists
It is a regular file
fs::exists(file) 會檢查傳入的路徑,不會搜尋符合條件的檔名。這裡的 folder / "notes.txt" 會使用 std::filesystem::path 將指定目錄與檔名組合起來,並依平台處理路徑分隔符號。若目標不在程序的目前工作目錄中,請用相同方式搭配自己的目錄路徑。相對路徑,例如 "notes.txt",是以程序的目前工作目錄為基準解析;目前工作目錄由程式的啟動環境設定,不會自動以執行檔所在目錄為基準。若要查看目前工作目錄,請呼叫 fs::current_path();若要變更程序的工作目錄,請使用 fs::current_path(path),並處理回報的任何檔案系統錯誤。只需檢查單一位置時,從已知目錄組合出路徑通常更清楚。
exists 回答的是項目是否存在,不會判斷項目類型。只有一般檔案符合條件時,請使用 fs::is_regular_file(path);預期項目是目錄時,則使用 fs::is_directory(path)。如果程式沒有檔案系統存取權限,或路徑在檢查期間發生變化,這些檢查也可能無法提供可用結果。若程式需要區分這些情況,請使用接受 std::error_code 的多載,並將錯誤與回傳的布林值分開檢查。
例如,std::error_code ec; const bool found = fs::exists(path, ec); 可讓呼叫端同時檢查 found 和 ec:結果為 false 且沒有錯誤,表示找不到該路徑;若錯誤已設定,則表示檢查無法完成的原因。不帶錯誤碼參數的多載會在發生檔案系統錯誤時擲出例外。如果程式需要在預期的檔案系統問題發生時繼續執行,請選用錯誤碼版本;否則,擲出例外的版本能讓簡單的檢查保持易讀。檢查完成後,路徑所指的項目也可能在稍後開啟前改變,因此應將檢查結果視為查詢當下的答案,而不是保證後續操作一定成功。
範例使用 std::filesystem,並自行建立暫存測試資料。如果建立目錄或檔案失敗,程式會印出準備訊息並以非零狀態返回。清理守衛會在正常結束時嘗試移除暫存目錄,並忽略清理錯誤。查詢使用會擲出例外的多載;若檔案系統例外未被捕捉而逸出 main,程式可能終止,因此無法保證清理守衛的解構函式會執行。正常執行時,輸出就是上方顯示的兩行。程式碼與輸出區塊均保持原文不變,區塊中顯示的標籤仍為英文。