我无法使用ofstream函数

时间:2019-06-27 05:11:03

标签: c++

您好,很抱歉,答案是否明确。我对编程还是很陌生,需要一些指导。

此函数应该只将它接收到的三个字符串参数之一写入我已经生成的txt文件中。当我运行程序时,该功能似乎正常运行,并且cout语句显示信息在字符串中,并且确实成功通过了。问题是运行程序后,我去检查txt文件,发现它仍然是空白。

我正在Visual Studio Professional 2015上使用C ++ 17。

void AddNewMagicItem(const std::string & ItemKey,
                     const std::string & ItemDescription,
                     const std::string &filename)
{
    const char* ItemKeyName = ItemKey.c_str();
    const char* ItemDescriptionBody = ItemDescription.c_str();
    const char* FileToAddItemTo = filename.c_str();
    std::ofstream AddingItem(FileToAddItemTo);
    std::ifstream FileCheck(FileToAddItemTo);
    AddingItem.open(FileToAddItemTo, std::ios::out | std::ios::app);
    if (_access(FileToAddItemTo, 0) == 0)
    {
        if (FileCheck.is_open())
        {
            AddingItem << ItemKey;
            std::cout << ItemKey << std::endl;
        }
    }
    AddingItem.close(); // not sure these are necessary
    FileCheck.close(); //not sure these are necessary
}

当您将字符串传递给ItemKey参数时,这应该在.txt文件上打印一条消息。

非常感谢您的帮助,请原谅我,因为我也是stackoverflow的新手,在格式化此问题时可能会犯一些错误或不够清楚。

添加:谢谢所有回答此问题的人以及您的所有帮助。我感谢您的帮助,并衷心感谢大家对这个主题的帮助,评论和意见。愿您的代码每次都能编译,并且您的代码评论总是会被注释。

2 个答案:

答案 0 :(得分:1)

主要问题

std::ofstream AddingItem(FileToAddItemTo); 

打开文件。用

再次打开
AddingItem.open(FileToAddItemTo, std::ios::out | std::ios::app); 

导致流失败。

解决方案

将打开模式移动到构造函数(std::ofstream AddingItem(FileToAddItemTo, std::ios::app);)中,然后删除手动打开。

请注意,仅需要app打开模式。 ofstream表示out模式已设置。

注意:如果用户无权访问该文件,则无法打开该文件。无需对此进行单独测试。我发现先测试打开的文件,然后再调用perror或类似的针对特定目标的调用,以提供有关失败原因的详细信息,这是有用的功能。

请注意,流中可能有多个different statesis_open有点偏。您想检查所有这些,以确保IO事务成功。在这种情况下,文件已打开,因此如果只检查is_open,则会错过failbit。读取时一个常见的相关错误仅是测试EOF并以失败的读取循环结束,该读取将永远不会到达文件末尾(or reading past the end of the file by checking too soon)。

AddingItem << ItemKey;

成为

if (!(AddingItem << ItemKey))
{
    //handle failure
}

有时,您将需要更好的粒度来确定确切发生了什么,以便正确处理错误。检查状态位,并检查perror和特定于目标的状态 诊断如上。

侧面问题

不建议同时打开多个fstreams进行读写的文件。不同的流将为同一文件提供不同的缓冲视图,从而导致不稳定。

可以尝试通过单个ostream读取和写入相同的文件,但是很难正确地完成。经验法则是将文件读入内存,然后关闭文件,编辑内存,然后打开文件,写入内存,然后关闭文件。如果可能的话,请保留文件的内存副本,这样就不必重新读取文件。

如果需要确定已正确写入文件,请先写入文件,然后将其读回,解析并确认信息正确。验证时,不允许再次写入文件。不要尝试对此进行多线程处理。

详细信息

这是一个小例子,用来说明哪里出了问题以及哪里出了错。

#include <iostream>
#include <fstream>

int main()
{
    std::ofstream AddingItem("test");
    if (AddingItem.is_open()) // test file is open
    {
        std::cout << "open";
    }
    if (AddingItem) // test stream is writable
    {
        std::cout << " and writable\n";
    }
    else
    {
        std::cout << " and NOT writable\n";
    }
    AddingItem.open("test", std::ios::app);
    if (AddingItem.is_open())
    {
        std::cout << "open";
    }
    if (AddingItem)
    {
        std::cout << " and writable\n";
    }
    else
    {
        std::cout << " and NOT writable\n";
    }
}

假设工作目录有效,并且用户具有编写测试的权限,我们将看到程序输出为

open and writable
open and NOT writable

这表明

std::ofstream AddingItem("test");

打开文件,然后

AddingItem.open("test", std::ios::app);

使文件保持打开状态,但将流置于不可写的错误状态,以迫使您处理试图同时在同一流中打开两个文件的潜在逻辑错误。基本上是说:“对不起戴夫,我恐怕不能这样做。”没有Undefined Behaviour或没有完整的Hal 9000血洗。

不幸的是,要获取此消息,您必须查看正确的错误位。在这种情况下,我用if (AddingItem)查看了所有这些内容。

答案 1 :(得分:0)

作为已经给出的问题评论的补充:

如果要将数据写入文件,我不明白为什么要使用std::ifstream。只需std::ofstream

您可以通过以下方式将数据写入文件:

const std::string file_path("../tmp_test/file_test.txt"); // path to the file
std::string content_to_write("Something\n"); // content to be written in the file

std::ofstream file_s(file_path, std::ios::app); // construct and open the ostream in appending mode

if(file_s) // if the stream is successfully open
{
    file_s << content_to_write; // write data
    file_s.close(); // close the file (or you can also let the file_s destructor do it for you at the end of the block)
}
else
    std::cout << "Fail to open: " << file_path << std::endl; // write an error message

正如您所说的对编程来说还很陌生,我已经明确评论了每一行,以使其更易于理解。

希望对您有帮助。


编辑:

有关更多说明,您尝试打开3次文件(在写入模式下两次,在读取模式下两次)。这是导致您出现问题的原因。您只需在写入模式下打开一次文件即可。

此外,检查输入流是否打开也不会告诉您输出流是否也打开。请记住,您打开了一个文件流。如果要检查它是否正确打开,则必须通过相关对象而不是另一个对象进行检查。