递归创建文件和文件夹

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
// // 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);
在Qt中,可以使用递归函数来创建文件。你可以在项目的头文件中声明一个函数,例如`QString createMultipleFolders(const QString path)`,并在源文件中实现它。 你可以参考以下代码示例: ```cpp // widget.h 头文件 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QDir> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); QString createMultipleFolders(const QString path); // 创建文件 private: Ui::Widget *ui; }; #endif // WIDGET_H ``` ```cpp // widget.cpp 源文件 #include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); } Widget::~Widget() { delete ui; } QString Widget::createMultipleFolders(const QString path) { QDir dir(path); if (!dir.exists()) { if (dir.mkpath(path)) { return "文件夹创建成功"; } else { return "文件夹创建失败"; } } return "文件夹已存在"; } ``` 在上述示例中,`createMultipleFolders`函数使用`QDir`类来递归创建文件。首先,它检查指定路径下的文件夹是否存在。如果不存在,它使用`mkpath`函数来创建文件。如果文件夹创建成功,函数返回"文件夹创建成功",否则返回"文件夹创建失败"。如果文件夹已经存在,则函数返回"文件夹已存在"。 在你的应用程序中,你可以通过调用`createMultipleFolders`函数并传递路径作为参数来递归创建文件123 #### 引用[.reference_title] - *1* *2* *3* [使用Qt的QDir/QFile类创建文件、以时间命名的dat/txt等文件、从文件中读写数据等操作](https://blog.csdn.net/m0_49456900/article/details/124928129)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值