将数据写入磁盘时的异常处理

时间:2018-05-04 08:23:08

标签: c++ file

我正在编写一个采用记录流(如学生记录)的应用程序,并将所有记录异步写入磁盘。有数十亿条记录,所以我需要将它们分成4MB的文件。抛出异常时文件是什么样的?如果我的记录无法写入磁盘,我会丢失数据吗?

1 个答案:

答案 0 :(得分:1)

这不仅是您必须担心的例外情况。您还必须考虑写入失败(可能会或可能不会抛出异常)。如果您有兴趣确保文件格式化更正,您实际上并不需要关心精确枚举哪些错误,因为您需要以相同的方式对待它们。如果出现错误,我建议让低级写入代码抛出异常。然后,您的更高级别代码可以统一处理所有失败,作为抛出的异常。

使用RAII和try ... catch可以在这种输出代码中提供最小异常保证(不会泄漏资源或无法维护不变量)。

为了提供强有力的保证,您可以尝试实现回滚操作,以便在发生异常时撤消任何写入操作。但是,该回滚代码必须始终有效;它绝不能抛出异常(noexcept)。该要求无法满足,因为无法保证执行文件IO操作的任何回滚都能正常工作。

但是你可以通过将写操作分成两部分来提供强有力的保证。更改文件格式,以便文件的开头有一个标题部分,它记录文件中的记录数。然后按如下方式写入文件。

  1. 阅读标题以发现文件中的记录数。
  2. 在文件中向前移动到新记录应该开始的位置。如果记录长度相等,则可以通过搜索操作完成。
  3. 撰写新记录。
  4. 提交(刷新)这些写入。
  5. 回头看。
  6. 将新记录计数写入标题。
  7. 提交写作。
  8. 将任何写入或提交失败视为整个操作的失败。您必须假设发生在自动提交的成功写入永远不会出现失败的提交操作(应该是无操作)。在实践中,除了远程文件系统之外,这可能是一个安全的假设。

    这种方案的缺点是写入文件需要两次写操作,两次刷新(提交)操作和两次搜索操作,如果你不得不做很多写操作,这可能会很昂贵。冲洗操作特别昂贵。

    尽管有许多写操作,但仍然可以提供高吞吐量的高级技术(例如日志记录)。 RDBMSes和NoSQL数据存储使用它们。您可以更好地使用现有的第三方RDBMS或NoSQL数据存储,而不是尝试自己实现它们。