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,程式可能終止,因此無法保證清理守衛的解構函式會執行。正常執行時,輸出就是上方顯示的兩行。程式碼與輸出區塊均保持原文不變,區塊中顯示的標籤仍為英文。