手机版

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上的翻译)


总结

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

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

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

相关文章:

宋朝第八位皇帝是谁?人们记住了他是因为他的绘画 06-15

明朝服饰发型是什么样的?民间女子和贵妇其实差别很大 06-15

盘点唐朝的7位传奇女人,不仅有女皇帝,而且还有个女宰相 06-14

从历史视角看,北宋“积贫积弱”吗? 06-14

各个朝代的诗人 《古代诗人名录》10856位大全集 卷一(1—900位) 06-13

宋朝出名的皇帝有哪些?北宋九位皇帝排名,赵匡胤无悬念排第一,著名书法家排倒数第二 06-13

宋朝的中央制度:为了掌控国家,宋朝采取了哪些制度? 06-12

一代诗宗——宋代诗人杨万里 06-12

宋朝和明朝只隔了89年 却感觉两个王朝相差几百年 06-11

明朝国子监祭酒 ,三代出三位祭酒、五位尚书 06-11