fstream !fail() and is_open()

fstream !fail() and is_open()

本文关键字:open is and fstream fail      更新时间:2023-10-16

我想通过 fstream将数据写入文件,并输出是否成功是否成功。我也想编写尽可能少的代码。大约是C 03。

解决方案1(似乎是最佳):

std::fstream file;
file.open("test.txt",std::ios_base::out); // sets failbit to true if open fails?
file << data; // what happens here if !file.is_open()?
file.close(); // and here? does close() work when writing data failed?
if (file)
    std::cout << "Success";
else
    std::cout << "Failed";
file.clear(); // for again usage. But what happens if file failed to open?
              // Or data failed to be written? Or file failed to be closed?
              // Is data waiting in stream to be written to next opened file?

解决方案2:

std::fstream file;
file.open("test.txt",std::ios_base::out);
if (file.is_open())
{
    file << data;
    file.close();
}
if (file) // if only writing data fails, is failbit reset by close()?
    std::cout << "Success";
else
    std::cout << "Failed";
file.clear();

解决方案3:

// is this solution overkill?
std::fstream file;
file.open("test.txt",std::ios_base::out);
if (file.is_open())
{
    file << data;
    if (!file)
    {
        std::cout << "Failed";
        file.clear();
    }
    file.close();
    if (file)
        std::cout << "Success";
    else
        std::cout << "Failed (again)";
}
else
    std::cout << "Failed";
file.clear();

它们都是等效的吗?

任何解决方案实际上都会相当复杂,因为您将通常希望以不同的方式处理不同类型的错误。例如,如果您无法打开文件,则要告诉用户,而不仅仅是输出失败。没有能力打开文件是您真正期望的错误。在另一方面,如果写操作失败,您需要其他错误处理。

因此,我建议立即检查is_open之后试图打开文件,并适当处理错误然后。

后来的错误更为罕见,但可能更严重。许多人情况,仅检查之后仅检查错误是可以接受的关闭,但是每当发生错误时,您可能应该删除部分编写(并因此损坏)文件。同样的人如果您的程序在编写时出于某些其他原因失败数据:关闭文件并删除。(我倾向于使用raii为此,具有commit功能,当所有输出都已完成。该提交关闭文件,并且如果关闭成功,请设置一个标志;如果未设置标志时攻击器被称为,破坏者关闭文件,忽略任何错误,然后将其删除。)

至于使用 clear():我想不出我会使用它的情况在输出流。iostream类并不是为重复使用,并且内部状态太多,无法轻松重置。输入,如果有格式错误,但此考虑不适用于输出流,所以我只是忽略它。(当然,一旦您打电话 clear,您无法知道是否有什么在成功与否之前。)

如果您的目标是在尽可能少的行中实现此功能,那么这可能会使您尽可能接近:

std::ofstream file("test.txt");
if (file.is_open())
{
    if (file << data)
    {
        std::cout << "Success";
    }
    else
    {
        std::cout << "Failed";
    }
    file.close();
}
else
{
    std::cout << "Failed";
}

无需致电clear()输出流。此外,<<还返回对ofstream的引用,因此您可以在IF-条件中检查它,而不是以后检查。

如果您想要更多的描述性错误处理(例如,根据错误是什么不同),则需要更多代码。