递归创建文件和文件夹

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;
}
原文地址:https://www.cnblogs.com/fangkm/p/1426528.html