近期项目上遇到这个问题,这两天刚好有朋友问到,顺便整理了一下
不管是使用FILE类,还是std::fstream,都会发现在写文件对象时有时候会出现一个类似flush的函数调用。其实这类函数的作用就是将应用程序调用类似write时写入到系统内存的数据强制写入(刷新)磁盘。那么为什么需要先写入内存呢,其实是操作系统给每个正在使用的文件分配了一块缓冲区,在读文件时是先从磁盘上将数据拷贝到缓冲区中再拷贝到应用程序读取缓冲区,在写文件时只有当这个缓冲区写满之后才把其中的数据一起送到磁盘上的文件。通过这种方式来提高系统的效率,因为在操作磁盘数据时,一次性操作大块的数据比多次操作小块数据在效率上来的快得多。
但有时我们需要数据立即写入磁盘以防丢失,或者是其他进程需要实时读取该文件时都需要使用到flush操作,使文件大小随时更新
在文件操作上这里还是推荐C语言的FILE结构
FILE* file;
//fopen是以共享方式打开文件,也就是说其他线程或进程可以同时打开该文件,比如其他程序需要实时读取数据时
//在高版本VS中被认为是不安全的函数,需要在工程属性中关闭SDL检查
file = fopen("test.txt", "wb");
if (!file) return;//一定要检测文件指针
//准备文件句柄,用以实时刷新文件大小
HANDLE hFile= (HANDLE)_get_osfhandle(_fileno(file));
//写文件
//b.flush();//数据刷新到硬盘
//刷新文件大小,可根据自己实际需要控制::FlushFileBuffers(hIndex);刷新频
::FlushFileBuffers(hFile);
打开文件就不多说了
以上代码使用到了三个关键函数
_get_osfhandle(_fileno(file));
_fileno(file);
FlushFileBuffers(hIndex)
_get_osfhandle
函数原型:intptr_t _get_osfhandle(int fd);
作用:检索与已指定的文件说明符的操作系统句柄的文件。
参数:现有文件描述符
返回值:操作系统的文件句柄,该函数返回 INVALID_HANDLE_VALUE (- 1) 并将 errno 设置为 EBADF,则指示无效的文件句柄
备注:关闭_get_osfhandle打开的文件,调用 _close。 调用_close也关闭基础句柄,因此,调用原始句柄的 Win32 函数 CloseHandle 是不必要的。
_fileno
函数原型:int _fileno(FILE *stream);
作用:获取与流有关的文件描述符
参数:指向 FILE 结构的指针
返回值:文件描述符号
FlushFileBuffers
函数原型:BOOL FlushFileBuffers(HANDLE hFile)
作用:刷新指定文件的缓冲区,并将所有已缓存的数据写入文件。(刷新了文件大小)
参数:文件句柄
返回值:成功返回非零,失败返回零,可调用GetLastError查看.