想要进行文件/目录的监测、创建、删除等操作,有好几种函数可以实现,但因为不同操作系统不兼容,可能同一个函数在linux可用,windows就不可用,而windows本身又有ansi、utf8、unicode好几种编码,所有函数都支持ANSI路径也就是纯英文路径,但遇到中文路径大部分操作函数就失效,总结就是这些函数简直乱成一锅粥。
这里做个备忘录,整理一下windows下可用的文件/目录操作函数。每个函数的详细介绍、参数解释,请自行前往微软MSDN查看。
优先使用宽字符集版本函数
比如_stat函数有_stat()
和_wstat()
宽字符集版本,优先使用宽字符集版本,以便更好的支持中文路径或其他非ANSI语言。
判断文件或目录是否存在
_waccess_s()
或_stat()
都可以,_waccess_s()
更简便。
_waccess_s
_waccess_s()
是_access()
函数的宽字符集更安全版本,可判断文件或目录是否存在(官方链接)。
返回值,0=存在,2或ENOENT=不存在。
1 2 3 4 5 6 7 8 9 | // 文件 if (_waccess_s(L"c:\\test\\test.exe", 0) == 0) // 目录 if (_waccess_s(L"c:\\test", 0) == 0) // 用变量 wstring path(L"c:\\test\\test.exe"); if (_waccess_s(path.data(), 0) == 0) |
_stat
_stat()
也可以判断文件或目录是否存在(官方链接),但是用此函数需要先申明一个结构体变量用于保存文件的详细权限,只用于判断文件是否存在是没必要这么麻烦。
另外不带下划线的stat()
函数只能对纯英文路径判断,不能判断带中文的路径,我被这个函数坑了很久。
创建目录
1 2 3 4 5 6 7 | // 参数2是指定文件/目录属性,如没有特殊需求可为空指针 // 直接用字符串 CreateDirectory(L"c:\\test", nullptr); // 使用变量 CreateDirectory(wstring.data(), nullptr); |
移动文件
1 | MoveFile(wstring_filepath.data(), wstring_newpath.data()); |
复制文件
1 | CopyFile(wstring_filepath.data(), wstring_newpath.data(), FALSE); |
删除文件
1 | DeleteFile(wstring_filepath.data()); |
重命名
网上介绍的rename()函数不支持中文。我直接用复制后删除的办法。
1 2 3 4 | if (_waccess_s(wstring_filepath.data(), 0) == 0) { if (CopyFile(wstring_filepath.data(), wstring_newfilepath.data(), FALSE)) DeleteFile(wstring_filepath.data()); } |
删除目录
因为函数只能删除空目录,所以可以直接写一个封装函数遍历删除目录内的所有文件和子目录。需要删除目录的时候直接调用此函数即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | void remove_allfiles(const wstring& wstrDir) { if (wstrDir.empty()) { return; } WIN32_FIND_DATA findData; const wstring wstrTempDir = wstrDir + L"\\*"; const HANDLE hFind = FindFirstFile(wstrTempDir.c_str(), &findData); if (hFind == INVALID_HANDLE_VALUE) { return; } do { // 忽略"."和".."两个结果 if (wcscmp(findData.cFileName, L".") == 0 || wcscmp(findData.cFileName, L"..") == 0) { continue; } wstring wstrFileName; wstrFileName.assign(wstrDir); wstrFileName.append(L"\\"); wstrFileName.append(findData.cFileName); if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)// 是否是目录 { remove_allfiles(wstrFileName); } else { DeleteFile(wstrFileName.c_str()); } } while (FindNextFile(hFind, &findData)); FindClose(hFind); RemoveDirectory(wstrDir.c_str()); } |
文章评论