【问题标题】:Force read on disk with std::ifstream instead of the file cache使用 std::ifstream 而不是文件缓存强制读取磁盘
【发布时间】:2011-11-01 00:43:55
【问题描述】:

我有一个程序,它使用 std::ifstream 从文件加载数据并将数据存储在一个结构中。之后,我验证我想要的数据是否在文件中。如果不是,我要求用户修改文件并按一个键。然后我重新加载文件。问题是即使用户修改了文件,我总是在文件中得到相同的数据,因为文件似乎在应用程序中缓存。我已经看到在 win32 API 中,可以使用标志 FILE_FLAG_NO_BUFFERING 来避免在读取文件时使用缓冲副本,但我想将该功能与 std::ifstream 一起使用。有没有办法将通过 win32 api 创建的句柄与 ifstream 一起使用,或者直接在 std::ifstream 中强制它?

这是一个“简化”的代码示例:

SomeStructure  s = LoadData(fileName);
while(!DataValid(s))
    s = LoadData(fileName);


SomeStructure LoadData(const std::string& fileName)
{
    std::ifstream fileStream;
    while(!OpenFileRead(fileName, fileStream))
    {
        std::cout<<"File not found, please update it";
        fileStream.close();
        //Wait for use input
        std::string dummy;
        std::getline(std::cin, dummy);
    }
    //... Read file, fill structure, and return
    std::string line;   
    while(std::getline(fileStream, line) && line!="")
    {
        //At this point, I can see that line is wrong
        StringArray namedatearray=Utils::String::Split(line, "|");
        assert(namedatearray.size()==2);
        //Add data to my structure ( a map)
     }
     fileStream.close();
     //return structure
}

bool OpenFileRead(const std::string& name, std::fstream& file)
{    
    file.open(name.c_str(), std::ios::in);
    return !file.fail();
}

谢谢。

编辑:当然,这是一个错误,因为我在两个非常相似的路径中有两次相同的文件。查看使用进程资源管理器打开的文件的句柄(而不是相对文件路径让我找到它)。

【问题讨论】:

  • 无缓冲 IO 在这里没有任何意义。你要么有错误的写入代码或有错误的读取代码。
  • 如果问题出在应用程序中的缓存,正如您所声称的,那么无缓冲 I/O 对您没有帮助,因为无缓冲 I/O 意味着 内核中没有缓冲。它与应用程序的缓存数据无关。而且您不太可能让ifstream 使用无缓冲句柄,因为when you create an object with constraints, you have to make sure everybody who uses the object understands those constraints
  • 你是如何修改文件的?我们认为“修改”文件的许多事情实际上根本不修改文件,而是用修改后的新文件替换文件。
  • 对于编写代码,修改是用普通的旧记事本完成的(并在之后立即保存)。至于读取的部分,我已经在代码中添加了。

标签: c++ windows caching std ifstream


【解决方案1】:

与其认为这是由于某种“缓冲”,我会先寻找明显的东西。

  • 您确定用户正在更改您正在阅读的同一个文件吗?
  • 您确定重新加载数据会正确更新内存中的数据结构吗?
  • 您确定DataValid() 正在做您想做的事吗?

操作系统使用文件缓冲区来提高磁盘性能的事实通常在应用程序级别上是不可见的。只要您查看的是同一个文件,操作系统就知道用户更新了文件,如果您重新打开它,您就会看到更改的数据。如果数据甚至没有机会刷新到磁盘,那也不会影响您的应用程序。

【讨论】:

  • 1) 好吧,用户是我,而且只有文件的版本,所以我确定我正在更改文件的好版本。至于其余的,在我成功打开文件后,我逐行进入文件,我看到数据就像旧版本的文件,而不是新版本。让我认为这是由于应用程序缓冲的原因是,如果我重新加载我的应用程序,它将读取新版本。至于对文件的修改,它是用记事本完成的(并在之后保存)。我在应用程序级别遇到这样的问题实际上有点奇怪......
  • 您的应用程序是否可能有另一个句柄来处理在其他地方打开的文件?这可能有助于解释为什么重新加载您的应用程序有效。当您的应用程序关闭时,您打开的所有句柄都将关闭。
  • 嗯...这有点尴尬...当可视化我的程序的句柄(使用进程资源管理器)时,我意识到我现在在两个几乎相同的路径中使用了 2 个版本的文件(我在将本地存储库升级到 tortoise svn 到 1.7 时出错,所以我不得不创建一个新的,并且仍在使用第一个存储库的解决方案。
  • @Jean-PhilippeJodoin:不用担心,每个人都会遇到这种情况。 :)
猜你喜欢
  • 2013-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 2013-02-22
相关资源
最近更新 更多