递归创建文件和文件夹

WIndows API函数CreateFile和CreateDirectory用于创建文件和目录,但设想这样一种情况:需要创建文件C:\test\test.txt,但是C:\test\目录不存在,简单地调用CreateFile不会成功了,创建目录也是一样。

我在Windows API找了很久,没找到能满足要求的函数,Shell API里也没有,于是只能靠自己实现了。

传入目录时,有些人习惯于在尾部加反斜杠,有些又没加反斜杠,为了方便编程,先封装一个方法来规范一下:

// 若bAddSpec 为真,则确保szDst路径末尾带有"\", 若bAddSpec为假,则去除lpszPath末尾的"\"或"/"
template < size_t nSize >
inline 
void  ModifyPathSpec( TCHAR ( & szDst)[nSize], BOOL  bAddSpec )
{
    
int  nLen  =  lstrlen( szDst );
    ASSERT( nLen 
>   0  );
    TCHAR  ch  
=  szDst[ nLen  -   1  ];
    
if ( ( ch  ==  _T( ' \\ ' ) )  ||  ( ch  ==  _T( ' / ' ) ) )
    {
        
if ! bAddSpec )
        {
            szDst[ nLen 
-   1  ]  =  _T( ' \0 ' );
        }
    }
    
else
    {
        
if ( bAddSpec )
        {
            szDst[ nLen ] 
=  _T( ' \\ ' );
            szDst[ nLen 
+   1  ]  =  _T( ' \0 ' );
        }
    }
}

首先讨论创建文件夹的情况,创建文件夹时主要是个递归过程,首先判断上级目录是否存在,

如果不存在,则递归创建上级目录.代码如下:

// 嵌套创建文件夹
inline BOOL  CreateDirectoryNested( LPCTSTR  lpszDir )
{
    
if ( ::PathIsDirectory( lpszDir ) )  return  TRUE;

    TCHAR   szPreDir[ MAX_PATH ];
    _tcscpy_s( szPreDir, lpszDir );
    
// 确保路径末尾没有反斜杠
    ModifyPathSpec( szPreDir, FALSE );

    
// 获取上级目录
    BOOL  bGetPreDir   =  ::PathRemoveFileSpec( szPreDir );
    
if ! bGetPreDir )  return  FALSE;

    
// 如果上级目录不存在,则递归创建上级目录
     if ! ::PathIsDirectory( szPreDir ) )
    {
        CreateDirectoryNested( szPreDir );
    }

    
return  ::CreateDirectory( lpszDir, NULL );
}
创建文件目录后,直接调用CreateFile就可以创建文件了.代码如下:
// 嵌套创建文件,bOverride为TRUE表示覆盖原已存在的文件
inline BOOL  CreateFileNested( LPCTSTR lpszFile, BOOL bOverride  =  TRUE )
{
    
if ( ::PathFileExists( lpszFile ) ) return  TRUE;

    TCHAR   szDir[ MAX_PATH ];
    _tcscpy_s( szDir, lpszFile );

    
// 获取文件目录
    BOOL  bGetDir   =  ::PathRemoveFileSpec( szDir );
    
if ! bGetDir ) return  FALSE;

    
// 创建文件目录
     if ! CreateDirectoryNested( szDir ) ) return  FALSE;

    DWORD  dwCreate 
=   bOverride ? CREATE_ALWAYS:OPEN_ALWAYS;
    HANDLE hFile 
=  ::CreateFile( lpszFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        dwCreate, FILE_FLAG_BACKUP_SEMANTICS, NULL );

    
if ( hFile  ==  INVALID_HANDLE_VALUE)
        
return  FALSE;

    ::CloseHandle( hFile );
    
return  TRUE;
}

你可能感兴趣的:(文件夹)