关于ofstream写文件机器重启偶发内容丢失的问题

背景:在vm虚拟机上,通过ofstream创建文件,机器重启后偶发内容消失。

1) 原版代码

代码

std::ofstream fout("test.txt");

fout << "test";

fout.close();

2)问题解释

fopen 写入文件不一定写入磁盘_commit()

在C语言中,使用fopen函数打开文件进行写入时,数据通常会被写入到操作系统提供的文件系统缓存中,而不是直接写入到磁盘上。这种机制可以提高程序的性能,因为它允许程序在多个写操作之间累积数据,然后在合适的时候(例如,程序结束、调用fflush函数或操作系统决定将缓存内容写入磁盘时)将数据写入磁盘。

如果你需要确保数据已经被写入磁盘,而不是仅仅停留在操作系统的缓存中,你可以采取以下几种方法:

1. 使用fflush函数

fflush函数可以用来刷新输出或更新文件流。当你调用fflush时,它会将所有未写的数据从文件流缓冲区传输到文件中。对于输出文件流,这会导致数据被写入磁盘。

#include <stdio.h>

FILE *fp = fopen("example.txt", "w");

if (fp != NULL) {

fputs("Hello, world!", fp);

fflush(fp); // 确保数据被写入磁盘

fclose(fp);

}

2. 使用fsync函数

如果你正在使用POSIX兼容的操作系统(如Linux或UNIX),你可以使用fsync函数来同步一个文件的描述符。这确保了所有对该文件描述符的写操作都已从内核缓冲区传输到磁盘。

#include <unistd.h>

#include <fcntl.h>

int fd = open("example.txt", O_WRONLY);

if (fd != -1) {

write(fd, "Hello, world!", 13);

fsync(fd); // 确保数据被写入磁盘

close(fd);

}

3. 程序终止时自动刷新和同步

在某些情况下,当程序正常终止时(例如,通过exit函数),操作系统会自动刷新并同步所有打开文件的缓冲区。然而,这不是一个可靠的方法来确保在程序执行期间的数据完整性,特别是在需要即时数据持久化的场景中。

4. 使用_commit函数(特定于Windows)

在Windows平台上,可以使用_commit函数来提交文件流的缓冲区到磁盘。这对于需要确保数据立即写入磁盘的应用程序非常有用。

#include <io.h>

#include <fcntl.h>

int fd = _open("example.txt", _O_WRONLY);

if (fd != -1) {

_write(fd, "Hello, world!", 13);

_commit(fd); // 确保数据被写入磁盘

_close(fd);

}

结论

根据你的具体需求和运行环境(如跨平台或特定于Windows),你可以选择合适的方法来确保数据写入磁盘。在大多数情况下,使用fflushfsync(在POSIX系统上)是足够好的选择。对于Windows平台,使用_commit可以提供额外的控制。

3) 解决

     目前下述代码通过测试

  

std::ofstream fout("test.txt");

fout << "test";

fout.close();

FILE *file =NULL;

errno_t err = fopen_s(&file,"test.txt","a");

if(NULL != file){

fflush(file);

_commit(_fileno(file))

fclose(file);

}

linux 系统没有 _commit 系统调用

在 Linux 系统中,commit 系统调用通常与事务型文件系统如 XFS、Btrfs 以及某些数据库的实现相关,而不是直接作为一个独立于这些系统的通用系统调用。在传统的文件系统(如 ext4)中,并没有直接的 commit 系统调用。不过,你可以通过其他机制来达到类似的效果,尤其是在涉及持久化数据更新的场景中。

理解 commit 的概念

在事务型文件系统中,commit 操作通常指的是确保所有自上次 commit 以来进行的写操作都被物理地写入磁盘。这对于数据库和需要高可靠性的应用程序尤其重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值