C++ 如何编写文件,然后将其读回以验证其内容,确保您';我们得到了什么';它在磁盘上,而不是缓存上
我在Windows上使用本机/C++/Win32/MFC代码通过MFC序列化保存文档文件。在编写过程中,我插入了自己的CFile派生类,使我能够在编写数据时访问数据。这允许我在数据输出到文件时计算数据的校验和(或哈希等) 保存文件后,我希望允许验证文件的选项。这样做的想法是重新打开文件,并通过验证校验和/散列等来读取它 不过,我想知道,是否有可能在刚写完文件后,当我马上读回文件时,操作系统会给我未写的数据。在这种情况下,测试并没有真正告诉我文件在磁盘上看起来很好C++ 如何编写文件,然后将其读回以验证其内容,确保您';我们得到了什么';它在磁盘上,而不是缓存上,c++,windows,winapi,mfc,filesystems,C++,Windows,Winapi,Mfc,Filesystems,我在Windows上使用本机/C++/Win32/MFC代码通过MFC序列化保存文档文件。在编写过程中,我插入了自己的CFile派生类,使我能够在编写数据时访问数据。这允许我在数据输出到文件时计算数据的校验和(或哈希等) 保存文件后,我希望允许验证文件的选项。这样做的想法是重新打开文件,并通过验证校验和/散列等来读取它 不过,我想知道,是否有可能在刚写完文件后,当我马上读回文件时,操作系统会给我未写的数据。在这种情况下,测试并没有真正告诉我文件在磁盘上看起来很好 我的担心是正确的吗?如果是这样,
我的担心是正确的吗?如果是这样,有没有办法避免此问题?如果您使用的是CFile,您可以调用以确保所有内容都写入磁盘。根据文件
virtual void Flush( );
强制将文件缓冲区中剩余的任何数据写入文件
我不知道这个问题的答案。不过,我知道该去哪里找 保证数据被安全地写入磁盘,无论发生什么情况——甚至是电源故障。他们一定在做你需要的事情,他们的代码是开源的,并且有漂亮的注释 SQLite中单个事务中的所有更改 完全或根本没有,即使将更改写入 磁盘被中断 程序崩溃 操作系统崩溃 或者是停电 上一段的声明在SQLite中进行了广泛的检查 回归测试套件,使用模拟 操作系统崩溃和断电对数据库文件的影响 失败
如果确实要这样做,则可以通过指定和/或在打开文件时避免磁盘缓存和缓冲。注意使用这些选项会使事情复杂化 正在打开文件或设备时,没有用于数据读取和写入的系统缓存。此标志不影响硬盘缓存或内存映射文件。 使用文件\u标志\u无缓冲标志成功使用CreateFile打开的文件有严格的要求,有关详细信息,请参阅
一个更简单的替代方法是在关闭文件句柄之前调用。我的猜测是,与所有其他文件抽象一样,这只是将程序的缓存刷新到操作系统。无法保证这会实际刷新到磁盘。@edA-qamort-ora-y但如果您使用另一个操作系统调用再次读取数据,它将是正确的regardless@Nerdtron只需刷新缓冲区。我的理解是Windows最终会告诉磁盘驱动程序将缓冲区刷新到磁盘。如果磁盘驱动程序不能做到这一点(“性能优化”),那么您对此无能为力。我手头没有,但我相信SQLServer的PSS有几篇博客文章提到这个问题是导致日志文件损坏的主要原因。但基本上:告诉Windows刷新文件,它应该刷新文件。除非磁盘驱动程序对其撒谎,否则Windows或您无法检测到这种情况。@Nerdtron我在MSDN上找不到任何保证文件关闭时将被刷新的文档,但请注意-您说您来自
CFile
,因此可能会将Close
重写为Flush(); CFile::Close()
?@Nerdtron我已经有一段时间没有输入MFC源代码了,但是您可以进入CFile::Close和CFile::~CFile,看看是否为您完成了刷新有趣的,谢谢您的提示!我来看看他们的代码。SQLite不能保证这一点,因为这是不可能的。除非有人发明了无电源运行的磁盘@David Heffernan请阅读SQLITE保证,我已经在我的回答中发布了该保证。该保证不是你在回答中所说的。您说过即使断电,数据也会写入磁盘。@ravenpoint我相信这是因为SQLite在每个数据库中都有一个小日志,这是操作系统外部的一种机制。请注意,保证不是数据完全写入或根本不写入,而是更改完全写入或根本不写入。如果电源故障中断了提交,文件中仍然会有垃圾漂浮,但日志知道这一点。写入文件。关上把手。用无用的缓冲器填充闸板,以强制冲洗。删除缓冲区。读取文件。(如果计算机的RAM大于虚拟进程空间,则无法工作)@Ambeco更重要的是,它将对计算机上的任何其他进程产生可怕的影响。我不认为我想在这个进程中填充RAM。