c++ ifstream 文件不结束_C/C++编程笔记:你不知道的windows保存文件的坑
序
對于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上的翻譯)
總結
緩存的存在是操作系統為了更好方便我們讀寫數據,避免因為磁盤的慢速,影響讀寫操作;
但是如果不清楚其中的原理,可能在特殊情況時,不知道如何處理問題。
當然如果大家沒有緊急情況出現,或者對數據寫入時間不敏感,可以直接忽略;還是用標準寫文件的方式,畢竟更加通用。
如果覺得我寫的還不錯的話,求贊,求關注哦!(^▽^)
總結
以上是生活随笔為你收集整理的c++ ifstream 文件不结束_C/C++编程笔记:你不知道的windows保存文件的坑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python获取系统当前时间并转utc时
- 下一篇: 微软KinectV2深度传感器在Ubun