隨筆-88  評論-77  文章-48  trackbacks-0
          在編程時,經(jīng)常有一些針對目錄的操作,如打開目錄對話框選擇一個目錄,直接創(chuàng)建多級目錄,直接刪除多級目錄,判斷某個目錄是否存在等。本文就這些問題給出編程實現(xiàn)方法,并給出詳細(xì)的程序代碼,供各位編程愛好者參考。

          一、判斷目錄是否存在:

          ??C++ Builder中提供了檢查文件是否存在的函數(shù)FileExists,但沒有提供檢查目錄是否存在的函數(shù),我們可以用Windows API函數(shù)FindFirstFile實現(xiàn)這個功能。程序?qū)崿F(xiàn)如下:

          設(shè)char *Dir為帶判斷的目錄
          bool Exist;????????????????????????????????????????????// 最后結(jié)果,表示目錄是否存在
          if(Dir[strlen(Dir)]=='\\')Dir[strlen(Dir)-1]='\0';????// 先刪除最后的“\”
          WIN32_FIND_DATA wfd;??????????????????????????????????// 查找
          HANDLE hFind=FindFirstFile(Dir,&wfd);??????????????????
          if(hFind==INVALID_HANDLE_VALUE)Exist=false;????????????// 沒有找到配備,目錄肯定不存在
          else
          {
          ????if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) // 檢查找到的結(jié)果是否目錄
          ????????Exist=true;??????????????????????????????????????// 是目錄,目錄存在
          ????else
          ????????Exist=false;????????????????????????????????????// 是目錄,目錄不存在
          ????FindClose(hFind);
          }

          二、打開目錄選擇對話框選擇一個目錄:

          ??大多專業(yè)軟件在要求輸入目錄的編輯框旁都放了一個按鈕,點擊后打開一個目錄窗口,很多編程愛好者也希望能掌握這個方法。實現(xiàn)這個功能要調(diào)用Windows API函數(shù)SHBrowseForFolder,完整聲明為WINSHELLAPI LPITEMIDLIST WINAPI SHBrowseForFolder(LPBROWSEINFO lpbi),返回一個ITEMIDLIST類型的指針,通過這個指針調(diào)用函數(shù)SHGetPathFromIDList可以確定所選擇的目錄的全名稱。入?yún)锽ROWSEINFO結(jié)構(gòu)的指針,這個結(jié)構(gòu)較為復(fù)雜,成員如下所示:

          HWND hwndOwner;????????// 擁有對話框的窗口,可以設(shè)置為Application->Handle
          LPCITEMIDLIST pidlRoot; // ITEMIDLIST類型的指針,表示在哪個路徑下選擇,一般可以設(shè)置為NULL
          LPSTR pszDisplayName;??// 選擇后,所選目錄的名稱(不包含父級目錄)被拷貝到這個指針指向的位置
          LPCSTR lpszTitle;??????// 作為標(biāo)題顯示在對話框中目錄樹的上面,可以根據(jù)實際情況設(shè)置
          UINT ulFlags;??????????// 標(biāo)志位,有點復(fù)雜,一般設(shè)置為BIF_RETURNONLYFSDIRS
          BFFCALLBACK lpfn;??????// 回調(diào)函數(shù),一般不用,設(shè)置為NULL
          LPARAM lParam;??????????// 預(yù)定義的對話框傳遞給回調(diào)函數(shù)的值
          int iImage;????????????// 與所選目錄相關(guān)聯(lián)的圖標(biāo)在系統(tǒng)圖標(biāo)集合中的索引
          可以看出,使用函數(shù)SHBrowseForFolder還真麻煩,普通愛好者掌握它確實有一定的難度,現(xiàn)給出完整程序段如下:
          #include <shlobj.h>????????????????????// 必須包含的頭文件
          char SelectedDir[MAX_PATH];??????????????// 最終結(jié)果
          BROWSEINFO bi;??????????????????????????// 入?yún)?br />char FolderName[MAX_PATH];??????????????// 所選目錄名稱,例如選擇C:\Windows\Font,則為Font
          LPITEMIDLIST ItemID;????????????????????// 所選目錄的系統(tǒng)標(biāo)志指針

          memset(SelectedDir, 0, MAX_PATH);??????????????// 初始化最終結(jié)果
          memset(&bi, 0, sizeof(BROWSEINFO));????// 初始化入?yún)⑺袛?shù)據(jù)
          bi.hwndOwner = Application->Handle;
          bi.pszDisplayName = FolderName;
          bi.lpszTitle = "請選擇目錄";????????????// 改成自己希望的
          bi.ulFlags=BIF_RETURNONLYFSDIRS;
          ItemID = SHBrowseForFolder(&bi);??????// 調(diào)用函數(shù),打開目錄選擇對話框
          if(ItemID)
          {
          ????SHGetPathFromIDList(ItemID, SelectedDir);??????// 獲取所選目錄的全名
          ????GlobalFree(ItemID);??????????????????????// 返回的ItemID占用了系統(tǒng)資源,不要忘了釋放
          }

          三、直接建立多級目錄:

          ??Windows API提供了建立目錄的函數(shù)CreateDirectory,但是調(diào)用前要保證父目錄必須存在,否則會失敗。其實,有時越級建立多級目錄很有用,因為在建立目錄特別是建立多層目錄時,層層加以判斷會大大地增加程序的復(fù)雜程度。如何實現(xiàn)這個功能呢?本人用遞歸方法設(shè)計了一個可以直接建立多級目錄的函數(shù),現(xiàn)說明如下,供各位朋友參考。

          bool MakeDirectoryEx(const AnsiString &P)??// 入?yún)榇蛩銊?chuàng)建的目錄名,根據(jù)操作結(jié)果返回"true"或"false"
          {
          ????if(P.IsEmpty())return false;
          ????int len=P.Length();
          ????char *Path=P.c_str();
          ????if(Path[len-1]=='\\')
          ????{
          ????????len--;
          ????????Path[len]='\0';
          ????}??????????????????????????????????????// 刪除末尾的"\"
          ????AnsiString Dir=Path;
          ????// 分開父目錄和本身目錄名稱
          ????AnsiString Parent;
          ????for(int i=len-1;i>0;i--)
          ????{
          ????????if(Dir.IsPathDelimiter(i))
          ????????{
          ????????????Parent=Dir.SubString(0,i);
          ????????????break;
          ????????}
          ????}
          ????if(Parent.IsEmpty())return false; // 目錄名稱錯誤
          ????bool Ret=true;
          ????if(Parent.Length()>3)??????????// 如果長度小于3,表示為磁盤根目錄
          ????????Ret=DirectoryExistEx(Parent.c_str());// 檢查父目錄是否存在
          ????if(!Ret)Ret=MakeDirectoryEx(Parent);??// 父目錄不存在,遞歸調(diào)用創(chuàng)建父目錄
          ????if(Ret)????????????????????????????????????????// 父目錄存在,直接創(chuàng)建目錄
          ????{
          ????????SECURITY_ATTRIBUTES sa;
          ????????sa.nLength=sizeof(SECURITY_ATTRIBUTES);
          ????????sa.lpSecurityDescriptor=NULL;
          ????????sa.bInheritHandle=0;
          ????????Ret=CreateDirectory(Path,&sa);
          ????}
          ????return Ret;
          }
          ????可以看出基本方法是:
          先檢查父目錄是否存在,這里用到的函數(shù)DirectoryExistEx可以按照前面介紹的方法設(shè)計;
          如果父目錄存在,則直接創(chuàng)建目錄,否則自我調(diào)用創(chuàng)建父目錄。


          四、直接刪除整個目錄:

          ??在DOS下有一個Deltree命令,用來刪除整個目錄,這是一個很有用的功能,可惜,Windows API提供的函數(shù)RemoveDirectory只能刪除控目錄,就像DOS的RD命令一樣。編程實現(xiàn)這個功能同樣需要遞歸方法,基本流程是:

          查找目錄下的所有文件和目錄,即調(diào)用API函數(shù)FindFirstFile、FindNextFile(*.*)
          如果找到文件,則強制刪除。所謂強制刪除,即刪除前先調(diào)用SetFileAttributes把它的屬性設(shè)置為Normal,然后調(diào)用DeleteFile刪除它。
          如果找到目錄,則進行自我調(diào)用,即開始遞歸過程。
          如果沒有找到目錄,即表示為控目錄,調(diào)用RemoveDirectory直接刪除。
          具體程序代碼如下:

          bool DeleteDirectoryEx(const AnsiString &P)
          {
          ????if(P.IsEmpty() || P.Length()<4)return false;????????// 參數(shù)長度必須大于3,即不能為磁盤根目錄或空白
          ????int len=P.Length();
          ????char *Path=P.c_str();
          ????AnsiString Dir=Path;
          ????if(Path[len-1]!='\\')Dir=Dir+'\\';
          ????AnsiString Files=Dir+"*.*";
          ????WIN32_FIND_DATA wfd;
          ????HANDLE hFind=FindFirstFile(Files.c_str(),&wfd);
          ????bool Ret=true;
          ????AnsiString Tmp;
          ????if(hFind!=INVALID_HANDLE_VALUE)
          ????{
          ????????bool bFind=true;
          ????????while(bFind)
          ????????{
          ????????????if(wfd.cFileName[0]!='.') // . ..
          ????????????{
          ????????????????Tmp=Dir+wfd.cFileName;
          ????????????????if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
          ????????????????{ // 刪除所有子目錄
          ????????????????????Ret=Ret&&DeleteDirectoryEx(Tmp.c_str(),false);
          ????????????????}else
          ????????????????{ // 刪除所有文件
          ????????????????????SetFileAttributes(Tmp.c_str(),FILE_ATTRIBUTE_NORMAL);
          ????????????????????Ret=Ret&&DeleteFile(Tmp.c_str());
          ????????????????}
          ????????????}
          ????????????bFind=FindNextFile(hFind,&wfd);
          ????????}
          ????????FindClose(hFind);
          ????}
          ????if(Ret)return RemoveDirectory(Path);
          ????return false;
          }
          posted on 2006-04-29 20:46 崛起的程序員 閱讀(310) 評論(0)  編輯  收藏 所屬分類: c/c++
          主站蜘蛛池模板: 皋兰县| 连南| 邻水| 鄯善县| 铅山县| 皮山县| 青浦区| 叙永县| 延安市| 临沂市| 宁明县| 昭觉县| 子洲县| 阿坝县| 彰化县| 甘德县| 庐江县| 孟津县| 安丘市| 广水市| 宁波市| 巴彦县| 乐陵市| 浦北县| 琼海市| 鱼台县| 漳平市| 石河子市| 余庆县| 仙游县| 宁陕县| 锦州市| 镇远县| 五原县| 余干县| 汨罗市| 佛冈县| 江川县| 洛川县| 大理市| 大渡口区|