http://blog.csdn.net/lgouc/article/details/8166522
- 使用system函数调用系统命令"md"
注意:字符串变量的话赋值时要使用双斜杠"\\":
system("md C:\\newfolder\\");
如果需要动态新建目录的话:
char *path = "C:\\newfolder\\";
char swap[255];
sprintf(swap, "md %s", path);
system(swap);
不用判断返回值,系统会自动将错误信息打印到标准输出上.
- _mkdir()
#include <direct.h>
_mkdir("C:\\newfolder");//新建
_rmdir("C:\\newfolder");//删除
#include<io.h>
_access("C:\\newfolder");//判断文件夹是否存在
缺点是不能一下新建多层文件夹,可以裁剪字符串一级一级创建
如何新建多层目录:
//这里的const是对函数的使用者而言的,其实函数内部修改了该const字符串,但又还原了
- void initPath(const char *path)
- {
- assert(path!= NULL);
- // 一层层判断目录是否已存在,不存在就新建
- // 这里的字符串最后一个字符正常情况下是'\'
- // 所以最后可以不用再判断了
- // 之所以说上面一点是因为对_mkdir来说
- // "D:\document"和"D:\document\"没有区别
- char *tmp = (char *)path;
- while (*tmp)
- {
- if (*tmp == '\\')
- {
- *tmp = '\0';
- if (_access(path, 0))// 头文件io.h
- {
- if (_mkdir(path))
- {
- #ifdef _DEBUG
- fprintf(stderr, "Failed to create directory %s:%s\n",
- path, strerror(errno));
- #endif
- }
- }
- *tmp = '\\';
- }
- ++tmp;
- }
- }
- CreateDirectory()
该API也不能新建多层文件夹,而且要打印该函数的出错信息也很复杂.Windows这一套真真的让人恶心.思路是一样的,先一层一层判断文件夹是否存在,如果不存在就新建.判断文件夹是否存在使用GetFileAttributes()函数,如果函数返回-1,说明文件/文件夹不存在;否则如果返回的属性有FILE_ATTRIBUTE_DIRECTORY,说明文件夹已存在.
- void createDirectory(const char *path)
- {
- assert(path!= NULL);
- char *tmp = (char *)path;
- LPVOID lpMsgBuf;
- while(*tmp)
- {
- if (*tmp == '\\')
- {
- *tmp = '\0';
- DWORD fileAttr = GetFileAttributes((LPCSTR) path);
- if (fileAttr == 0xFFFFFFFF || !(fileAttr & FILE_ATTRIBUTE_DIRECTORY))
- {
- if (!CreateDirectory((LPCTSTR) path, NULL))
- {
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL
- );
- MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
- }
- }
- *tmp = '\\';
- }
- ++tmp;
- }
- // Free the buffer.
- LocalFree(lpMsgBuf);
- }
关于FormatMessage函数,要多说一点关于Windows API错误(失败)信息的获取.看到网上说《Multitheading Applications inWin32(侯捷译)》书里讲述通过宏MTVERIFY就可以知道调用的Windows API函数错在什么地方:
- /*
- * MtVerify.h
- *
- * Error handling for applications in
- * "Multitheading Applications in Win32"
- *
- * The function PrintError() is marked as __inline so that it can be
- * included from one or more C or C++ files without multiple definition
- * errors. For the examples in this book, this works fine.
- * To use the PrintError() in an application, it should be taken out,
- * placed in its own source file, and the "__inline" declaration removed
- * so the function will be globally available.
- */
- #pragma comment(lib, "USER32")
- #include <crtdbg.h>
- #define MTASSERT(a) _ASSERTE(a)
- #define MTVERIFY(a) if (!(a)) PrintError(#a, __FILE__, __LINE__, GetLastError())
- __inline void PrintError(LPSTR linedesc, LPSTR filename, int lineno, DWORD errnum)
- {
- LPSTR lpBuffer;
- char errbuf[256];
- #ifdef _WINDOWS
- char modulename[ MAX_PATH];
- #else // _WINDOWS
- DWORD numread;
- #endif // _WINDOWS
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- errnum,
- LANG_NEUTRAL,
- (LPTSTR) &lpBuffer,
- 0,
- NULL);
- wsprintf(errbuf, "\nThe following call failed at line %d in %s:\n\n"
- "%s\n\nReason: %s\n", lineno, filename, linedesc, lpBuffer);
- #ifdef _WINDOWS
- GetModuleFileName(NULL, modulename, MAX_PATH);
- MessageBox(NULL, errbuf, modulename, MB_ICONWARNING | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
- #else
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), errbuf, strlen(errbuf), &numread, FALSE);
- Sleep(3000);
- #endif
- exit(EXIT_FAILURE);
- }
经过本人亲测,可用.那么上面的函数可以改为:
- #include "MtVerify.h"
- void createDirectory(const char *path)
- {
- assert(path != NULL);
- char *tmp = (char *)path;
- while(*tmp)
- {
- if (*tmp == '\\')
- {
- *tmp = '\0';
- DWORD fileAttr = GetFileAttributes((LPCSTR) path);
- if (fileAttr == (DWORD) -1 || !(fileAttr & FILE_ATTRIBUTE_DIRECTORY))
- {
- MTVERIFY(CreateDirectory((LPCTSTR) path, NULL));
- }
- *tmp = '\\';
- }
- ++tmp;
- }
- span style="white-space:pre"> </span>}
- MakeSureDirectoryPathExists()
这绝对是一个暴力的函数,啥都不说了,直接用:
MTVERIFY(MakeSureDirectoryPathExists(path));
别忘了加上两句:
#include <ImageHlp.h>
#pragma comment(lib, "ImageHlp.lib")
加上一点:该函数强制要求参数字符串以反斜杠'\'结尾,如果不以'\'结尾,最后一层文件夹不会建立.
- 最后再说几个判断文件夹是否存在的方法
- PathFileExists() 可以判断文件或者文件夹是否存在:
if (PathFileExists(path)) {...}
- MFC的CFileFind类
使用CFileFind的成员函数FindFile(),FindNextFile()和IsDirectory().
- void createDirectory(const char *path)
- {
- assert(path != NULL);
- char *tmp = (char *)path;
- CFileFind ff;
- // 不能搜索硬盘分区根目录,所以要略过
- // 如果严谨一些可以判断是否已到字符串结尾
- while (*tmp++ != '\\') {}
- while (*tmp)
- {
- if (*tmp == '\\')
- {
- *tmp = '\0';
- if (ff.FindFile(path, 0))
- {
- // 必须要调用一次FindNextFile()后才能判断
- // IsDirectory(),不知道为什么
- // 因为同一目录下的文件夹和文件也不能完全重名
- // 所以不用担心会找到多个同名的文件/文件夹
- ff.FindNextFile();
- if (!ff.IsDirectory())
- {
- MTVERIFY(CreateDirectory((LPCTSTR) path, NULL));
- }
- }
- else
- {
- MTVERIFY(CreateDirectory((LPCTSTR) path, NULL));
- }
- *tmp = '\\';
- }
- ++tmp;
- }
- pan style="white-space:pre"> </span>}
如果是非MFC应用程序,要加头文件afx.h和Windows.h(在VC6.0下顺序还不能反了,蛋疼),并设置工程为"Use MFC in a Shared DLL".编译通过.
- 和上面相似,使用Win32 API FindFirstFile()和FindNextFile()
- void createDirectory(const char *path)
- {
- assert(path != NULL);
- char *tmp = (char *)path;
- // 不能搜索硬盘分区根目录,所以要略过
- // 如果严谨一些可以判断是否已到字符串结尾
- while (*tmp++ != '\\') {}
- WIN32_FIND_DATA wfd;
- while (*tmp)
- {
- if (*tmp == '\\')
- {
- *tmp = '\0';
- if (FindFirstFile(path, &wfd) == INVALID_HANDLE_VALUE ||
- !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
- {
- MTVERIFY(CreateDirectory((LPCTSTR) path, NULL));
- }
- *tmp = '\\';
- }
- ++tmp;
- }
- }
注: 上述处理的都是绝对路径(而且是以反斜杠结尾的绝对路径), 如果相对路径的话, 要稍作修改