【问题标题】:Filewrite not happening when ofstream pointer is in a std::map in C++当 ofstream 指针位于 C++ 中的 std::map 中时,文件写入不会发生
【发布时间】:2017-08-18 15:57:36
【问题描述】:

WRT 下面的代码,它编译得很好,也可以毫无例外地执行。但是没有内容被写入 javascript 文件。它是 0 字节。

std::map<std::string, std::shared_ptr<std::ofstream>> m_jsTabFilesMap;
m_jsTabFilesMap.insert({ fileKey, std::make_shared<std::ofstream>(jsFilename) });
auto jsFile = m_jsTabFilesMap[tabName];
(*jsFile).open(tabName + ".js");
*jsFile << contentofJSFile;  // write to JS file

不知道我错过了什么,如何让它写入文件。

[问题更新] 使用普通指针方法也会导致相同的结果。

std::map<std::string,std::ofstream*> m_jsTabFilesMap;
m_jsTabFilesMap.insert({ filekey, new std::ofstream(jsFilename)});

还尝试删除显式 Open() 调用,结果相同,没有任何内容写入文件。

【问题讨论】:

  • tabName的类型是什么?使用串联时可能很重要。
  • 要像这样调试代码,首先要简化。创建一个指向std::ofstream 的共享指针并弄清楚如何写入它。然后将其放入您的地图中,看看它是否仍然有效。几乎任何人都可以用这么少的 sn-p 代码告诉你。无法独立重现您的结果。
  • 打开文件时返回值是多少?我建议使用文件名创建一个字符串变量,然后传递给open()。这允许您在使用调试器时查看实际的文件名。
  • std::make_shared&lt;std::ofstream&gt;(jsFilename) 看起来您在此处打开了文件,或尝试打开。你试图在这里再次打开它(*jsFile).open(tabName + ".js");。如果第一次打开成功,则以流处于失败状态结束。
  • @codeLover 你不能复制它但你可以得到一个参考像auto&amp; jsFile = m_jsTabFilesMap[tabName];

标签: c++ c++11 stl std ofstream


【解决方案1】:

由于存储设备不能一次直接写入几个字节,而是整个扇区(通常是 4096 或 512字节)。在“刷新”任何缓冲区之前,您的数据实际上可能不会被写入或“可见”。当文件关闭或缓冲区已满(很可能很多 KB)时,这总是会发生。但是,如果您将其存储在地图中,您可能不会在检查之前等待它关闭?

使用std::ostream::flush 方法显式刷新文件。请记住,这样做会降低性能。

您还应该检查错误。默认情况下,C++ 流在大多数情况下不会抛出异常,即使打开文件失败,所以你想检查它的错误状态(例如 good()fail())。尽管如果您的代码暗示您的代码适用于正常的堆栈分配流,那么使用存储映射的版本也应该适用。

【讨论】:

    【解决方案2】:

    查看给定的代码 sn-p,文件流打开了两次。一次在这里:std::ofstream&gt;(jsFilename),另一次是(*jsFile).open(tabName + ".js");。重新打开文件流会将流置于错误状态,并且无法再写入。显而易见的解决方案是删除(*jsFile).open(tabName + ".js");

    下一个怪事是

    m_jsTabFilesMap.insert({ fileKey, std::make_shared<std::ofstream>(jsFilename) });
    auto jsFile = m_jsTabFilesMap[tabName];
    

    流被映射到fileKey 并使用tabName 访问。如果fileKey 不等于tabName,将返回不同的流。如果tabName 不存在于map 中,则map 不会失败、抛出异常或以任何方式警告您。它将创建一个全新的、默认构造的ofstream,并且必须打开这个流,如果文件已经被map 中的fstream 保持打开状态,它可能无法打开。您可以通过使用std::map::at 而不是operator[] 来阻止创建新的fstream 并获得std::out_of_range 异常

    通过额外检查以确保所有尝试的操作都成功执行,代码应如下所示:

    std::map<std::string, std::shared_ptr<std::ofstream>> m_jsTabFilesMap;
    
    std::shared_ptr<std::ofstream> temp = make_shared<std::ofstream>(jsFilename);
    if (*temp) // test if opened.
    {
        m_jsTabFilesMap.insert({ fileKey,  temp}); // only add if opened!
    }
    else
    {
        // handle error!
    }
    
    try
    {
        auto jsFile = m_jsTabFilesMap.at(tabName);
        if (! (*jsFile << contentofJSFile))  // write to JS file
        {
            // handle error
        }
    }
    catch (const std::out_of_range & )
    {
         // handle error
    }
    

    此时程序可能仍然无法运行,但您现在可以更好地确定原因。

    题外话:似乎不需要std::shared_ptr。其他人建议切换到std::unique_ptr。我会更进一步。可能根本不需要指针。

    std::map<std::string, std::ofstream> m_jsTabFilesMap; // no pointers 
    std::ofstream temp(jsFilename);
    if (temp)
    {
        m_jsTabFilesMap.emplace(fileKey, std::move(temp)); //emplace, not insert
    }
    else
    {
        // handle error
    }
    try
    {
        auto &jsFile = m_jsTabFilesMap.at(tabName);
        if (!(jsFile << contentofJSFile))
        {
            // handle error
        }
    }
    catch (const std::out_of_range &)
    {
        // handle error
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 2011-05-20
      相关资源
      最近更新 更多