C/C++编程笔记:你不知道的windows保存文件的坑

100次浏览     发布时间:2025-04-14 04:06:35    

对于c/c++来说,写文件是必不可少的事情。但是如果大家不仔细研究,真的会掉进某些坑里。

在某些紧急情况下,可能要保证数据安全且及时的写到磁盘上,否则就会有丢失的风险。

小文件可能还不那么明显,对于大文件来说,按照平常的方式,可能就出事了。

今天我就带大家来聊一聊这个问题。




读写文件

c语言中文件操作用的是 FILE*, 以及与之相关的打开,读,写,关闭等函数。

对应的是 fopen、fread、fwrite、fclose 等(fgets fputs 等就不在此继续展开了)。

但是在写文件的时候,我们如何保证数据被正确及时的写到磁盘上面了呢?

可能大家会说调用 fflush;很显然如果真的是这样,那今天我也不会写这篇文章了。

那为什么 fflush 不对呢?


缓存

我们可能都知道,文件读写,或者说一般的IO操作都会有缓存。

即磁盘文件被操作系统映射到系统的某个内存中缓存了;我们平常读写是会和缓存打交道。

操作系统根据我们当前操作情况,在缓存与磁盘文件之间进行数据交互。

而对于 fflush 来说,只能保证数据已经被写到了操作系统的文件缓存,不能保证已经写到了磁盘!

只有在 fclose 的时候才能确保缓存数据全部写到磁盘,然后关闭文件。


大家可能会问,那就在 fwrite 写完数据后,直接 fclose 不就行了。

是的,对于小文件来说可能确实如此。

但是对于大文件的时候,可能之前缓存里的数据还没有及时写到磁盘,后面的数据也需要写入;

虽然在 fclose 后会强制将缓存数据写到磁盘,但是可能会需要一点时间,而不巧此时断电了。


解决方案

windows提供的API中,有 CreateFile、ReadFile、WriteFile 和 CloseHandle 来处理IO操作。

其中 CreateFile 有个 dwFlagsAndAttributes 的参数,可以传递不同的属性。

对于我们遇到的问题可以向该参数设置为 FILE_FLAG_NO_BUFFERING 或 FILE_FLAG_WRITE_THROUGH 或者设置成它们相或后的值。

FILE_FLAG_NO_BUFFERING 表示读写文件时,不创建缓存;

FILE_FLAG_WRITE_THROUGH 表示在数据写到缓存后,立刻写入磁盘。

即要写入的文件如下打开即可:

// 打开文件
HANDLE hFileDst = ::CreateFileA(dst.toLocal8Bit().data(),
                             GENERIC_WRITE,
                             0,
                             NULL,
                             OPEN_ALWAYS,
                             /*FILE_FLAG_NO_BUFFERING |*/ FILE_FLAG_WRITE_THROUGH, // 设置flag
                             NULL);

    if (hFileDst == INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFileSrc);
        return;
    }

// 数据写入
int ret = ::WriteFile(hFileDst, m_dat, dwReadSize, &dwWriteSize, NULL);

需要注意的是 FILE_FLAG_NO_BUFFERING 设置后需要字节对应,文件存取的字节数必须是扇区尺寸的整倍数。

例如,如果扇区尺寸是512字节,程序就可以读或者写512,1024或者2048字节,但不能够是335,981或者7171字节。(这是MSDN上的翻译)


总结

缓存的存在是操作系统为了更好方便我们读写数据,避免因为磁盘的慢速,影响读写操作;

但是如果不清楚其中的原理,可能在特殊情况时,不知道如何处理问题。

当然如果大家没有紧急情况出现,或者对数据写入时间不敏感,可以直接忽略;还是用标准写文件的方式,毕竟更加通用。

相关文章:

唐朝吃相最难看的贪官,修祖坟累死县令,要升官献上妹子 04-15

科普:明朝流通的货币体系主要有哪些? 04-15

揭秘明朝五大军备神器,战无不胜攻无不克 04-15

明朝内阁制的演变过程:逐渐从一个秘书机构演变为行政机构 04-15

北宋汴梁是现在的哪个城市?北宋皇帝办公的地,一起来看看吧 04-15

C/C++编程笔记:你不知道的windows保存文件的坑 04-14

唐朝的地理位置? 唐朝巅峰时期版图最西到达哪里?千万不要被谭版地图给骗了 04-14

明朝南北榜案,不是科场舞弊案,朱元璋为什么要惩罚南方文人官僚? 04-14

为何明朝皇权明明是加强,明朝的言官们反而更有战斗欲? 04-14

明朝不为人知的北元,苟延残喘下的蒙古贵族 04-14