递归创建文件和文件夹

递归创建文件夹与文件

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/archive/2009/03/31/1426528.html

// // FilePath.h // /** \file FilePath.h */ #pragma once #include "vtString.h" #include <fstream> #include <io.h> /** * A portable class for reading directory contents. * * Example of use: \code for (dir_iter it("C:/temp"); it != dir_iter(); ++it) { if (it.is_hidden()) continue; if (it.is_directory()) printf("Directory: '%s'\n", it.filename().c_str()); else printf("File: '%s'\n", it.filename().c_str()); } \endcode */ class dir_iter { public: dir_iter(); dir_iter(const char*dirname); dir_iter(const wchar_t*dirname); ~dir_iter(); /// Returns true if the current object is a directory. bool is_directory(); /// Returns true if the current object is hidden. bool is_hidden(); /// Get the filename fo the current object. std::string filename(); std::wstring wfilename(); // Iterate the object to the next file/directory. void operator++(); // Test for inequality useful to test when iteration is finished. bool operator!=(const dir_iter &it;); long m_handle; private: struct _wfinddata_t m_data; }; //MBCS string 或者 Wide string vtString vtFindFileOnPaths(const vtStringArray &paths;, const char *filename); vtString2 vtFindFileOnPaths(const vtStringArray2 &paths;, const wchar_t *filename); bool vtCreateDir(const char *dirname); bool vtCreateDir(const wchar_t *dirname); void vtDestroyDir(const char *dirname); void vtDestroyDir(const wchar_t *dirname); int vtDeleteFile(const char *filename); int vtDeleteFile(const wchar_t *filename); const char *vtStartOfFileName(const char *szFullPath); const wchar_t *vtStartOfFileName(const wchar_t *szFullPath); vtString vtExtractPath(const char *szFullPath, bool bTrailingSlash); vtString2 vtExtractPath(const wchar_t *szFullPath, bool bTrailingSlash); bool vtPathIsAbsolute(const char *szPath); bool vtPathIsAbsolute(const wchar_t *szPath); vtString vtPathLevelUp(const char *src); vtString2 vtPathLevelUp(const wchar_t *src); vtString get_line_from_stream(std::ifstream &input;); vtString2 get_line_from_stream(std::wifstream &input;); //bFull为ture包括所有扩展名;否则最后一个扩展名 void vtRemoveFileExtensions(vtString& fname,bool bFull = false); void vtRemoveFileExtensions(vtString2& fname,bool bFull = false); //bFull为ture包括所有扩展名;否则最后一个扩展名 vtString vtGetExtensions(const vtString &fname;, bool bFull = false); vtString2 vtGetExtensions(const vtString2 &fname;, bool bFull = false); bool vtChangeFileExtension(vtString& input, const char *extension); bool vtChangeFileExtension(vtString2& input, const wchar_t *extension); bool vtFileExists(const char *fname); bool vtFileExists(const wchar_t *fname); #pragma comment(lib, "shell32.lib") bool vtCopyFile( const char* from,const char * to, bool bFailIfExists=true); bool vtCopyFile( const wchar_t* from,const wchar_t * to, bool bFailIfExists=true); bool vtCopyTree(const char* from,const char * to); bool vtCopyTree(const wchar_t* from,const wchar_t * to); bool vtFolderExists(const char *fname); bool vtFolderExists(const wchar_t *fname); bool vtFilePathExists(const char *fname); bool vtFilePathExists(const wchar_t *fname); int vtGetFileSize(const char *fname); int vtGetFileSize(const wchar_t *fname); void vtSetEnvironmentVar(const char* var, const char*value); void vtSetEnvironmentVar(const wchar_t* var, const wchar_t*value); #include "windows.h" bool vtGetModuleFullPath(const char* modulename,vtString& fullpath); bool vtGetModuleFullPath(const wchar_t* modulename,vtString2& fullpath); ///////////////////////////////////////////// // Open a file using a UTF-8 or wide character filename. FILE *vtFileOpen(const char *fname_mbcs, const char *mode); FILE *vtFileOpen(const wchar_t *fname_wide, const wchar_t *mode); vtString vtChooseFolder(HWND hWnd =NULL); vtString2 vtChooseFolder2(HWND hWnd=NULL);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值