C语言 FILE写文件中途断开磁盘驱动器测试(1)

注意, 该操作存在风险(数据可能会丢失), 谨慎操作

注意, 该操作存在风险(数据可能会丢失), 谨慎操作

注意, 该操作存在风险(数据可能会丢失), 谨慎操作

note

  • 1 实际使用场景中, 会出现,写文件过程中, 将驱动器从主机上断开,再重新插上一块新的驱动器(移动硬盘)
  • 2 未知:当断开驱动器时, 此时依然执行 fwrite函数写入文件, 文件是否能写入成功, 特作此实验
  • 3 其他平台,没有测试。

环境

  • windows11 64
  • VS 2019
  • U 盘模拟移动硬盘
  • fwrite 写入文件测试
  • 请阅读 fflush
  • 写同名文件测试

基于此次测试结论

  • fwrite 仅仅将数据写入 文件缓冲, 将数据写入文件 得 fflush 函数
  • 当写一个文件时, 中途取下U盘, 内核无法将缓存的数据写入文件, 即 调用fflush函数将失败, frwite 成功
  • 当写一个文件时,中途取下U盘,再次执行同名文件写入, 依然能将数据写入磁盘(本次测试中,创建文件使用的 "W"方式)
  • 当写一个文件时, 如果中途取下U盘, 再插入, 后面的数据依然无法写入成功
  • 当两个文件时, 第一个文件写入成功, 第二个文件写入失败(写入中途取下U盘), 模拟磁盘上存在其他文件, 重新插上U盘, 待系统修复U盘结束后, 第一个文件中的数据存在,第二个文件或无法打开 或 文件内容不全等

准备代码

1 准备测试代码

  • 测试代码如下,创建文件, 循环20次, 将数据一段固定数据写入文件

void call_write(const std::string& file_name)
{

	FILE* pfile = nullptr;
	errno_t ret = fopen_s(&pfile, file_name.c_str(), "w+");

	if (0 != ret)
	{
		std::cout << "\n 11111 ret=" << ret << "\n";
		return ;
	}

	const char parr[]{ "1234567890\n" };
	const size_t len = strlen(parr);

	for (int index = 0; index < 20; ++index)
	{
		if (len != fwrite(parr, 1, len, pfile))
		{
			std::cout << "22222, index << " << index << ", error_id=" << ferror(pfile) << "\n";
			break;
		}
		else
		{
			std::cout << "index=" << index << " succeeded to call fwrite, ";
		}

		int ret = fflush(pfile);
		std::cout << ", fflush_ret =" << ret << "\n";

		std::this_thread::sleep_for(std::chrono::seconds(2));
	}

	fclose(pfile);
	pfile = nullptr;
}

3. 准备测试U盘

测试情景1

1. 当正在写入文件途中,将驱动器取下

int main()
{
	///  1. 文件测试1
	call_write(std::string("E:\\1.txt"));
	return 0;
}

2. 情景1 输出结果

  • 输出 index=3时, 将U盘取下来,此时console输出结果
  • 可见, 当index=3输出后(此时已经取下U盘), 发现后面的7次 调用 fwrite 函数均成功, 但是, 调用 fflush 却失败了(返回值为 -1, )。 因为驱动器不在了, 无法将缓冲中的数据写入磁盘。 故而失败。

3. 文件内容

  • 既然存在写入成功,重新插上U盘,打开文件, 查看文件内容(灾难, )
  • 系统修复后, 可查看文件内容, 不过, 文件内容, 或为空, 或存在几行数据, 我测试了多次, 结果不一 , 其中一次情况如下:
  • 可见, 尽管程序执行了至少2次成功的fflush的调用, 但是修复后的文件中, 只有一行数据

测试情景2

1. 先创建文件,再将驱动器取下, 最后插上

  • 测试用例要写入20次, 20次内, 依次 完成, 先写入, 再取下, 最后插入的过程。
  • 输出index=2, 取下U盘, 输出 index=6, 插上U盘。 观察20次执行 结束后,的输出结果

情景2 输出结果

  • 可见, 当取下U盘后,index=3~index=5的过程中, 调用 fwrite 成功, 但是,调用fflush 失败, index=6 开始,后面的 fwrite 都成功, fflush调用失败
  • 结论,当U盘中途断开后, 尽管再次将U盘插上, 后面的写入依然无法成功

测试情景3

    1. 改调用代码如下, 写入两个文件, 当主线程main函数中睡眠10s时,开始将盘取下, 10s到之前, 将U盘再插入
int main()
{
	///  1. 文件测试1
	call_write(std::string("E:\\1.txt"));

	/// 主线程暂停, 重新插上U盘
	std::cout << "\n\n ====================== main_thread pause begin ======================= \n\n";
	std::this_thread::sleep_for(std::chrono::seconds(1 * 10));
	std::cout << "\n\n ====================== main_thread pause ended ======================= \n\n";

	/// 2. 文件测试2
	call_write(std::string("E:\\2.txt"));

	return 0;
}

2. 输出结果

  • 可见,两个文件写入全部成功, fwritefflush调用全部成功

3. 打开写入的文件

  • 可见, 文件写入成功

测试情景4

1. 写两个文件, 第一个文件 最后 13次时, 取下U盘, 格式化, 待到创建第二个文件前,,再插入U盘, 直到第二个文件20次写入结束

2. 输出结果

3. 分析

  • 这里, 多了一个格式化的步骤, 因为插上U盘, 系统提示驱动器存在问题,需要修复。
  • 可见,当创建第二个文件前, 保证驱动器时OK的, 文件可以创建成功并写入成功
  • 文件内容如下

4. 进一步测试

  • 如果不执行格式化呢?
  • 输出结果
  • 可见, 依然成功

测试情景5

1. 步骤:写一个文件, 写文件执行到中途,取下U盘, 再将U盘插上, 此时,执行结果

取下U 盘后,此时写入失败,

插上U盘, 再次执行程序写入同名文件, 此时结果

可见依然能写入成功

posted @ 2022-07-26 20:31  mohist  阅读(154)  评论(0编辑  收藏  举报