【问题标题】:How do I create a file that is modified if any duplicates are found如果发现任何重复项,如何创建修改的文件
【发布时间】:2020-07-20 02:10:00
【问题描述】:

我想要一个由用户提供的名称创建的文件。如果文件名已经存在,我希望在创建之前自动修改文件名。

if (GetFileAttributesA((name).c_str()) != INVALID_FILE_ATTRIBUTES)
{
    int num = 0;
    //If True: Modify File Name
    while (GetFileAttributesA((name + "" + to_string(num) + "").c_str()) != INVALID_FILE_ATTRIBUTES)
    {
        cout << (GetFileAttributesA((name + "" + to_string(num) + "").c_str()) != INVALID_FILE_ATTRIBUTES) << endl;
        num++;
    }
    CreateFileA((name + "" + to_string(num) + "" + ".txt").c_str(), NULL, NULL, NULL, 2, NULL, NULL);
    cout << "Created new file at: ";
    cout << (name + "" + to_string(num) + "" + ".txt").c_str() << endl;
}
else
{
    CreateFileA(name.c_str(), NULL, NULL, NULL, 2, NULL, NULL);
    cout << "Created new file at: ";
    cout << (name + ".txt").c_str() << endl;
}

第一次运行程序

Created new file at: Created new file at: D:\Users\Me\HD-Visual Studio Repos\Visual Studio Repo\McFG\Text Generator Function Generator\Generated txt\base.txt

第二次运行程序

Created new file at: Created new file at: D:\Users\Me\HD-Visual Studio Repos\Visual Studio Repo\McFG\Text Generator Function Generator\Generated txt\base1.txt

第三次运行程序

Created new file at: Created new file at: D:\Users\Me\HD-Visual Studio Repos\Visual Studio Repo\McFG\Text Generator Function Generator\Generated txt\base1.txt

到第三次时,它会再次开始创建副本。

name = D:\Users\Me\HD-Visual Studio Repos\Visual Studio Repo\McFG\Text Generator Function Generator\Generated txt\base

【问题讨论】:

  • 您正在检查的文件,GetFileAttributes 与您正在创建的文件不同。注意你在哪里输入num
  • 典型的问题是代码变得复杂而无用,计算多次相同的事情(实际上几乎由于错误而导致相同的事情)...
  • @JaedonKLB 我们都明白这一点,但是你你明白他的话吗?
  • @JaedonKLB 根本不使用GetFileAttributes,这会引入竞争条件。如果文件存在,CreateFile 有失败的标志。循环调用CreateFile,每次迭代创建一个新的文件名,直到创建成功
  • @bruno 如果循环正确处理错误,则不会。 GetLastError 会告诉他为什么 CreateFile 会失败。在这种情况下,循环 while CreateFile 仅以 ERROR_FILE_EXISTS 失败,其他任何情况都是致命错误,应该会中断循环

标签: c++ file winapi directory


【解决方案1】:

使用GetFileAttributes() 的方式会引入竞争条件。在您检查文件是否存在之后并且在您可以打开/创建它之前,另一个进程可以创建/删除该文件。如果文件已经存在,CreateFile() 具有使其失败的标志,您应该改用该功能。在您的示例中,将 dwCreationDisposition 参数设置为 2 (CREATE_ALWAYS) 会覆盖现有文件。将参数设置为 1 (CREATE_NEW)。根据documentation:

始终创建
2

总是创建一个新文件。

如果指定文件存在且可写,则函数覆盖该文件,函数成功,最后错误代码设置为 ERROR_ALREADY_EXISTS (183)。

如果指定的文件不存在并且是有效路径,则创建一个新文件,函数成功,最后错误代码设置为零。

...

CREATE_NEW
1

创建一个新文件,前提是它不存在。

如果指定的文件存在,则函数失败,最后一个错误代码设置为 ERROR_FILE_EXISTS (80)。

如果指定的文件不存在并且是可写位置的有效路径,则创建一个新文件。

例如:

string filename = name + ".txt";
int num = 0;
HANDLE hFile;

do
{
    hFile = CreateFileA(filename.c_str(), 0, 0, NULL, CREATE_NEW, 0, NULL);
    if ((hFile == INVALID_HANDLE_VALUE) && (GetLastError() == ERROR_FILE_EXISTS))
        filename = name + to_string(num++) + ".txt";
    else
        break;
}
while (true);

if (hFile != INVALID_HANDLE_VALUE)
{
    cout << "Created new file at: " << filename << endl;
    // use hFile as needed...
    CloseHandle(hFile);
}
else
{
    DWORD errCode = GetLastError();
    cerr << "Unable to create new file at: " << filename << ". Error " << errCode << endl;
    // error handling...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多