首页 > 代码库 > c++Builder 下的文件及目录操作

c++Builder 下的文件及目录操作

转自 http://blog.csdn.net/ktcserver/article/details/936329

一、判断目录是否存在:     
    
  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>   //   必须包含的头文件     
  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");