一、判斷目錄是否存在:
C++ Builder中提供了檢查文件是否存在的函數FileExists,indows 程序實現如下:
設char *Dir為帶判斷的目錄
bool Exist; // 最後結果,表示目錄是否存在
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) // 檢查找到的結果是否目錄
Exist=true; // 是目錄,目錄存在
else
Exist=false; // 是目錄,目錄不存在
FindClose(hFind);
}
二、打開目錄選擇對話框選擇一個目錄:
大多專業軟件在要求輸入目錄的編輯框旁都放了一個按鈕,點擊後打開一個目錄窗口,很多編程愛好者也希望能掌握這個方法。實現這個功能要調用Windows API函數SHBrowseForFolder,完整聲明為WINSHELLAPI LPITEMIDLIST WINAPI SHBrowseForFolder(LPBROWSEINFO lpbi),返回一個ITEMIDLIST類型的指針,通過這個指針調用函數SHGetPathFromIDList可以確定所選擇的目錄的全名稱。入參為BROWSEINFO結構的指針,這個結構較為復雜,成員如下所示:
HWND hwndOwner; // 擁有對話框的窗口,可以設置為Application->Handle
LPCITEMIDLIST pidlRoot; // ITEMIDLIST類型的指針,表示在哪個路徑下選擇,一般可以設置為NULL
LPSTR pszDisplayName; // 選擇後,所選目錄的名稱(不包含父級目錄)被拷貝到這個指針指向的位置
LPCSTR lpszTitle; // 作為標題顯示在對話框中目錄樹的上面,可以根據實際情況設置
UINT ulFlags; // 標志位,有點復雜,一般設置為BIF_RETURNONLYFSDIRS
BFFCALLBACK lpfn; // 回調函數,一般不用,設置為NULL
LPARAM lParam; // 預定義的對話框傳遞給回調函數的值
int iImage; // 與所選目錄相關聯的圖標在系統圖標集合中的索引
可以看出,使用函數SHBrowseForFolder還真麻煩,普通愛好者掌握它確實有一定的難度,現給出完整程序段如下:
#include <shlobj.h> // 必須包含的頭文件
包含這個文件需定義
#define NO_WIN32_LEAN_AND_MEAN //加了shlobj後必須定義的變量
char SelectedDir[MAX_PATH]; // 最終結果
BROWSEINFO bi; // 入參
char FolderName[MAX_PATH]; // 所選目錄名稱,例如選擇C:/Windows/Font,則為Font
LPITEMIDLIST ItemID; // 所選目錄的系統標志指針
memset(SelectedDir, 0, MAX_PATH); // 初始化最終結果
memset(&bi, 0, sizeof(BROWSEINFO)); // 初始化入參所有數據
bi.hwndOwner = Application->Handle;
bi.pszDisplayName = FolderName;
bi.lpszTitle = "請選擇目錄"; // 改成自己希望的
bi.ulFlags=BIF_RETURNONLYFSDIRS;
ItemID = SHBrowseForFolder(&bi); // 調用函數,打開目錄選擇對話框
if(ItemID)
{
SHGetPathFromIDList(ItemID, SelectedDir); // 獲取所選目錄的全名
GlobalFree(ItemID); // 返回的ItemID占用了系統資源,不要忘了釋放
}
三、直接建立多級目錄:
Windows API提供了建立目錄的函數CreateDirectory,但是調用前要保證父目錄必須存在,否則會失敗。其實,有時越級建立多級目錄很有用,因為在建立目錄特別是建立多層目錄時,層層加以判斷會大大地增加程序的復雜程度。如何實現這個功能呢?本人用遞歸方法設計了一個可以直接建立多級目錄的函數,現說明如下,供各位朋友參考。
bool MakeDirectoryEx(const AnsiString &P) // 入參為打算創建的目錄名,根據操作結果返回"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); // 父目錄不存在,遞歸調用創建父目錄
if(Ret) // 父目錄存在,直接創建目錄
{
SECURITY_ATTRIBUTES sa;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor=NULL;
sa.bInheritHandle=0;
Ret=CreateDirectory(Path,&sa);
}
return Ret;
}
可以看出基本方法是:
先檢查父目錄是否存在,這裡用到的函數DirectoryExistEx可以按照前面介紹的方法設計;
如果父目錄存在,則直接創建目錄,否則自我調用創建父目錄。
四、直接刪除整個目錄:
在DOS下有一個Deltree命令,用來刪除整個目錄,這是一個很有用的功能,可惜,Windows API提供的函數RemoveDirectory只能刪除控目錄,就像DOS的RD命令一樣。編程實現這個功能同樣需要遞歸方法,基本流程是:
查找目錄下的所有文件和目錄,即調用API函數FindFirstFile、FindNextFile(*.*)
如果找到文件,則強制刪除。所謂強制刪除,即刪除前先調用SetFileAttributes把它的屬性設置為Normal,然後調用DeleteFile刪除它。
如果找到目錄,則進行自我調用,即開始遞歸過程。
如果沒有找到目錄,即表示為控目錄,調用RemoveDirectory直接刪除。
具體程序代碼如下:
bool DeleteDirectoryEx(const AnsiString &P)
{
if(P.IsEmpty() || P.Length()<4)return false; // 參數長度必須大於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;
}
直接建立多級目錄可以用ForceDirectories
比如ForceDirectories("C://111//222//333");
即使不存在C:/111這個目錄,也會創建成功。
ExpandFileName() 返回文件的全路徑(含驅動器、路徑)
ExtractFileExt() 從文件名中抽取擴展名
ExtractFileName() 從文件名中抽取不含路徑的文件名
ExtractFilePath() 從文件名中抽取路徑名
ExtractFileDir() 從文件名中抽取目錄名
ExtractFileDrive() 從文件名中抽取驅動器名
ChangeFileExt() 改變文件的擴展名
ExpandUNCFileName() 返回含有網絡驅動器的文件全路徑
ExtractRelativePath() 從文件名中抽取相對路徑信息
ExtractShortPathName() 把文件名轉化為DOS的8·3格式
MatchesMask() 檢查文件是否與指定的文件名格式匹配
CreateDir() 創建新的子目錄
DeleteFile() 刪除文件
DirectoryExists() 判斷目錄是否存在
DiskFree() 獲取磁盤剩余空間
DiskSize() 獲取磁盤容量
FileExists() 判斷文件是否存在
FileGetAttr() 獲取文件屬性
FileGetDate() 獲取文件日期
GetCurrentDir() 獲取當前目錄
RemoveDir() 刪除目錄
SetCurrentDir() 設置當前目錄
下面就把這些函數作一一介紹:
⑴CreateDir()
原型:extern PACKAGE bool __fastcall CreateDir(const System::AnsiString Dir);
功能:建立子目錄,如果成功返回true,否則返回false
參數:Dir:要建立的子目錄的名字
例:Create("ASM");//在當前目錄下建立一個名為ASM的子目錄
⑵DeleteFile()
原型:extern PACKAGE bool __fastcall DeleteFile(const System::AnsiString FileName);
功能:刪除文件,如果成功返回true,否則返回false
參數:FileName:要刪除的文件名
例:if(OpenDialog1->Execute())DeleteFile(OpenDialog1->FileName);
⑶DirectoryExists()
原型:extern PACKAGE bool __fastcall DirectoryExists(const System:: AnsiString Name);
功能:檢測目錄是否存在,如果存在返回true,否則返回false
參數:Name:要檢測的目錄名
例:if(!DirectoryExists("ASM"))CreateDir("ASM");//如果ASM這個目錄不存在則創建之
⑷DiskFree()
原型:extern PACKAGE __int64 __fastcall DiskFree(Byte Drive);
功能:檢測磁盤剩余空間,返回值以字節為單位,如果指定的磁盤無效,返回-1
參數:Drive:磁盤的代號,0表示當前盤, 1=A,2=B,3=C 以此類推
例:ShowMessage(DiskFree(0));//顯示當前盤的剩余空間
⑸DiskSize()
原型:extern PACKAGE __int64 __fastcall DiskSize(Byte Drive);
功能:檢測磁盤容量,返回值以字節為單位,如果指定的磁盤無效,返回-1
參數:Drive:磁盤的代號,0表示當前盤, 1=A,2=B,3=C 以此類推
例:ShowMessage(DiskFree(0));//顯示當前盤的容量
⑹FileExists()
原型:extern PACKAGE bool __fastcall FileExists(const AnsiString FileName);
功能:檢測文件是否存在,如果存在返回true,否則返回false
參數:FileName:要檢測的文件名
例:if(FileExists("AAA.ASM"))DeleteFile("AAA.ASM");
⑺FileGetAttr()
原型:extern PACKAGE int __fastcall FileGetAttr(const AnsiString FileName);
功能:取得文件屬性,如果出錯返回-1
返回值如下表,如果返回$00000006表示是一個具有隱含和系統屬性的文件(4+2)
常量 值 含義
faReadOnly $00000001 只讀文件
faHidden $00000002 隱含文件
faSysFile $00000004 系統文件
faVolumeID $00000008 卷標
faDirectory $00000010 目錄
faArchive $00000020 歸檔文件
例:if(FileGetAttr("LLL.TXT")&0x2)ShowMessage("這是一個有隱含屬性的文件");
與此對應的有FileSetAttr() ,請自已查閱幫助系統
⑻FileGetDate()
原型:extern PACKAGE int __fastcall FileGetDate(int Handle);
功能:返回文件的建立時間到1970-1-1日0時的秒數
參數:Handle:用FileOpen()打開的文件句柄。
例:
int i=FileOpen("C://autoexec.bat",fmOpenRead);
ShowMessage(FileGetDate(i));
FileClose(i);
與此對應的有FileSetDate(),請自已查閱幫助系統
⑼GetCurrentDir()
原型:extern PACKAGE AnsiString __fastcall GetCurrentDir();
功能:取得當前的目錄名
例:ShowMessage(GetCurrentDir());
⑽RemoveDir()
原型:extern PACKAGE bool __fastcall RemoveDir(const AnsiString Dir);
功能:刪除目錄,如果成功返回true,否則返回false
參數:Dir:要刪除的目錄名
例:if(DiectoryExists("ASM"))RemoveDir("ASM");
⑾SetCurrentDir()
原型:extern PACKAGE bool __fastcall SetCurrentDir(const AnsiString Dir);
功能:設置當前目錄,如果成功返回true,否則返回false
參數:Dir:要切換到的目錄名
例:SetCurrentDir("C://WINDOWS");
轉載請注明出處。作者:四極管。廣西師范大學 電子工程學院大學生科技創新基地 郵箱:[email protected]。