我想使用GetTempFileName函数生成随机文件名,但在调用该函数时不创建文件本身。我想使用该函数来使用名称本身(并且不带扩展名),以便稍后我可以创建具有该特定名称的文件夹。由于没有类似的创建文件夹的函数,我只想获取 GetTempFileName 创建的字符串以便稍后创建文件夹。
LPTSTR wzTemp = new TCHAR[MAX_PATH];
GetTempFileName(strTemp, 0, 0, wzTemp);
CString tempFolder;
tempFolder = wzTemp;
Run Code Online (Sandbox Code Playgroud)
这是我的尝试,但在 GetTempFileName 之后立即创建文件。
知道我该如何调整这个吗?
GetTempFileName负责创建文件。如果您想创建一个唯一的目录,则必须编写自己的实现。使用GetTempFileName,然后删除该文件,并在其位置创建一个具有相同名称的目录注定会失败,因为TOCTOU竞争。
创建唯一名称的标准解决方案是使用 GUID 的字符串表示形式。您可以调用UuidCreate,然后调用UuidToString来获取一个。
如果 36 个字符在您的情况下不太实用,您将需要基于不太独特的算法(例如系统时间)和重试策略来编写自己的实现。
作为示例,下面是一个实现,它使用系统时间的字符串表示形式,表示为 64 位十进制数。这导致字符串表示形式最多为 19 个字符宽。
#include <Windows.h>
#include <iostream>
#include <string>
#include <system_error>
std::wstring GetTempDir(std::wstring const& root_dir) {
while (true) {
::SYSTEMTIME st{};
::GetSystemTime(&st);
::FILETIME ft{};
if (!::SystemTimeToFileTime(&st, &ft)) {
auto error_code{ ::GetLastError() };
throw std::system_error(error_code, std::system_category(),
"SystemTimeToFileTime()");
}
ULARGE_INTEGER ft_uli{ ft.dwLowDateTime, ft.dwHighDateTime };
auto dir_name{ std::to_wstring(ft_uli.QuadPart) };
auto dir_name_full{ root_dir + dir_name };
if (::CreateDirectoryW(dir_name_full.c_str(), nullptr)) {
return dir_name_full;
}
else {
auto error_code{ ::GetLastError() };
if (error_code != ERROR_ALREADY_EXISTS) {
throw std::system_error(error_code, std::system_category(),
"CreateDirectoryW()");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
此函数返回它创建的临时目录的完全限定路径,如果不能,则抛出异常。它需要根目录的字符串,包括结尾的反斜杠。如果目录已经存在,它会继续尝试,直到可以创建目录。
特别注意,不存在竞争条件。如果该函数成功,则该目录已创建。
可以按以下示例所示调用它:
int main() {
wchar_t path[MAX_PATH + 1]{};
::GetTempPathW(_countof(path), path);
auto temp_dir{ GetTempDir(path) };
std::wcout << L"Temporary directory created: " << temp_dir << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3316 次 |
| 最近记录: |