首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++Builder 目錄操作全攻略:存在性檢查、選擇對話框、多層建立與刪除

     編輯:VC 教學

前言

C++Builder 雖提供 FileExists 檢查檔案,但缺乏直接的目錄操作函式。本文整理四大常見目錄操作需求:判斷目錄是否存在、彈出選擇目錄對話框、建立多層目錄、遞歸刪除目錄樹,並提供完整的 Windows API 實作代碼。

一、判斷目錄是否存在

利用 FindFirstFile 搭配 FILE_ATTRIBUTE_DIRECTORY 屬性判斷。

bool DirectoryExists(const char* Dir)
{
    if (!Dir || !*Dir) return false;

    char path[MAX_PATH];
    strncpy(path, Dir, MAX_PATH - 1);
    path[MAX_PATH - 1] = '\0';

    // 移除結尾反斜線(根目錄 "C:\\" 除外)
    size_t len = strlen(path);
    if (len > 3 && path[len - 1] == '\\')
        path[len - 1] = '\0';

    WIN32_FIND_DATA wfd;
    HANDLE hFind = FindFirstFile(path, &wfd);
    if (hFind == INVALID_HANDLE_VALUE)
        return false;

    bool isDir = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
    FindClose(hFind);
    return isDir;
}

注意:FindFirstFile 也會匹配檔案,務必檢查屬性位確認是目錄。

二、目錄選擇對話框

方法 1:SHBrowseForFolder(標準 Shell 介面,支援網路芳鄰)


#include 

AnsiString SelectFolder(AnsiString Caption)
{
    BROWSEINFO bi = {0};
    char sDir[MAX_PATH] = {0};
    char FolderName[MAX_PATH] = {0};

    bi.hwndOwner = Application->Handle;
    bi.pszDisplayName = FolderName;
    bi.lpszTitle = Caption.c_str();
    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; // Vista+ 新樣式

    LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
    if (!pidl) return "";

    if (SHGetPathFromIDList(pidl, sDir))
    {
        CoTaskMemFree(pidl); // 必須釋放 PIDL
        AnsiString result = sDir;
        if (!result.IsEmpty() && result[result.Length()] != '\\')
            result += '\\';
        return result;
    }
    CoTaskMemFree(pidl);
    return "";
}

方法 2:SelectDirectory(VCL 封裝,介面類似開啟/儲存對話框,可新建資料夾)


#include 

AnsiString SelectDir(AnsiString Dir)
{
    // sdAllowCreate: 允許使用者新建資料夾
    // sdPerformCreate: 實際建立新資料夾
    // sdPrompt: 提示輸入路徑
    if (SelectDirectory(Dir, TSelectDirOpts() << sdAllowCreate << sdPerformCreate << sdPrompt, 0))
        return Dir;
    return "";
}

三、建立多層目錄

CreateDirectory 僅能建立單層,需遞歸或迭代分解路徑逐層建立。


bool ForceDirectories(const char* Dir)
{
    if (!Dir || !*Dir) return false;

    char path[MAX_PATH];
    strncpy(path, Dir, MAX_PATH - 1);
    path[MAX_PATH - 1] = '\0';

    // 移除結尾反斜線
    size_t len = strlen(path);
    if (len > 0 && path[len - 1] == '\\')
        path[len - 1] = '\0';

    // 逐層建立
    for (char* p = path + 3; *p; ++p) // 跳過 "C:\"
    {
        if (*p == '\\')
        {
            *p = '\0';
            if (!DirectoryExists(path))
            {
                if (!CreateDirectory(path, NULL))
                {
                    DWORD err = GetLastError();
                    if (err != ERROR_ALREADY_EXISTS)
                    {
                        *p = '\\';
                        return false;
                    }
                }
            }
            *p = '\\';
        }
    }

    // 建立最終目錄
    if (!DirectoryExists(path))
        return CreateDirectory(path, NULL) || GetLastError() == ERROR_ALREADY_EXISTS;

    return true;
}

或直接使用 VCL 封裝 ForceDirectories(AnsiString)(SysUtils.hpp)。

四、遞歸刪除目錄樹


bool DeleteDirectoryTree(const char* Dir)
{
    if (!Dir || !*Dir) return false;

    char searchPath[MAX_PATH];
    snprintf(searchPath, MAX_PATH, "%s\\*.*", Dir);

    WIN32_FIND_DATA wfd;
    HANDLE hFind = FindFirstFile(searchPath, &wfd);
    if (hFind == INVALID_HANDLE_VALUE) return false;

    bool success = true;
    do
    {
        if (strcmp(wfd.cFileName, ".") == 0 || strcmp(wfd.cFileName, "..") == 0)
            continue;

        char fullPath[MAX_PATH];
        snprintf(fullPath, MAX_PATH, "%s\\%s", Dir, wfd.cFileName);

        if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            // 遞歸刪除子目錄
            if (!DeleteDirectoryTree(fullPath))
                success = false;
        }
        else
        {
            // 刪除檔案(先移除唯讀屬性)
            SetFileAttributes(fullPath, FILE_ATTRIBUTE_NORMAL);
            if (!DeleteFile(fullPath))
                success = false;
        }
    }
    while (FindNextFile(hFind, &wfd));
    FindClose(hFind);

    // 最後刪除空目錄本身
    SetFileAttributes(Dir, FILE_ATTRIBUTE_NORMAL);
    return success && RemoveDirectory(Dir);
}

API 對照與選擇建議

需求推薦 API備註
檢查目錄存在FindFirstFile + FILE_ATTRIBUTE_DIRECTORYVCL 無直接對應
選擇目錄(含網路)SHBrowseForFolder介面較舊,Vista+ 加 BIF_NEWDIALOGSTYLE
選擇目錄(可新建)SelectDirectory (FileCtrl.hpp)VCL 封裝,介面熟悉但為英文
建立多層目錄ForceDirectories (SysUtils.hpp)VCL 內建,最簡便
刪除目錄樹遞歸 FindFirstFile + RemoveDirectoryVCL 無內建,需自行實作

實務提醒

  • 所有檔案/目錄操作前務必用 SetFileAttributes(..., FILE_ATTRIBUTE_NORMAL) 移除唯讀、隱藏、系統屬性,否則刪除/修改會失敗。
  • 路徑長度限制 MAX_PATH (260),超長路徑需加 \\\\?\\ 前綴並使用 Unicode 版 API(FindFirstFileW 等)。
  • 大量操作時建議停用 UI 重繪或使用背景執行緒,避免介面凍結。
  • 刪除系統關鍵目錄需管理員權限,UAC 環境下需嵌入 Manifest 或以管理員身分執行。

掌握這套目錄操作工具箱,即可在 C++Builder 中從容應對各類檔案系統管理需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved