.NET 中的事务性打开/写入/替换?

发布于 2024-12-06 04:01:55 字数 159 浏览 0 评论 0原文

我想也许我应该将其限制为 8k。我想每次打开一个文件并从头到尾写入。但是,如果由于某种原因(例如停电)它没有完成,我不想要损坏的数据。有没有办法可以打开/写入/关闭事务文件,这样除非成功,否则它不会替换以前的文件?

当我用谷歌搜索时,我得到了很多关于数据库事务和 ado 而不是文件的结果

I am thinking maybe i should restrict it to 8k. I'd like to open a file and write from start to end everytime. However if for some reason (say power outage) it doesnt complete i do not want corrupt data. Is there a way i can do a transactional file open/write/close so it doesnt replace the previous file unless its a success?

When i google i get many results on database transactions and ado instead of files

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羅雙樹 2024-12-13 04:01:55
  1. 写入临时文件,
  2. 删除旧文件,
  3. 只有写入成功才重命名临时文件。

为了防止在第二步之后第三步之前断电时数据丢失,您还需要执行一步:

  • 在程序启动时,检查是否有主文件被删除但尚未重命名的临时文件。如果找到任何文件,请对这些文件再次执行第三步。
  1. Write to a temporary file,
  2. Delete the old file
  3. Rename the remporary file only if the write succeeds.

To prevent data loss if you lose power after step two but before step three, you need one more step:

  • At program startup, check for temporary files that have their main files deleted but have not yet been renamed. If you find any, perform step three again for those files.
愿与i 2024-12-13 04:01:55

Windows Vista 及更高版本中的 NTFS 是事务性的。

我不相信您可以从纯托管代码访问它 - 您需要 P/Invoke 到 Win32 API。

一个好的起点是 CreateTransactionCommitTransactionRollbackTransactionCreateFileTransacted(以及其他 *Transacted) Win32 API 函数。

NTFS in Windows Vista and later is transactional.

I do not believe that you can access it from the pure managed code - you'll need to P/Invoke into Win32 API.

A good place to start would be CreateTransaction, CommitTransaction, RollbackTransaction, CreateFileTransacted (and other *Transacted) Win32 API functions.

迷爱 2024-12-13 04:01:55

我一直使用的 Mark Byer 解决方案略有不同:

  1. 将新内容写入与要替换的文件位于同一目录中的临时文件。
  2. 如果写入成功,将其重命名[1]为所需的文件。

重命名是原子的,因此如果成功,系统就不会处于未定义状态。如果失败,那么,系统仍处于原始状态并且您拥有系统重新启动时要替换的内容的备份(在临时文件中)。

我典型的命名约定如下:

/path/to/original/content.data

/path/to/original/.#content.data

如果系统在该过程中的某个位置关闭,则在重新启动应用程序时,您可以扫描 .#content.data 并将其呈现给用户,就像他们在系统出现故障时输入的内容一样,或者使用一些自定义魔法来决定它是否“完整”,以决定是否对内容进行重命名。数据。

我不知道你正在写什么样的数据,所以我无法帮助你决定那个“魔法”是什么,但如果它是一个 xml 文件,例如,你可以解析它的正确性,如果你不这样做得到一个意外的文件结尾,那么你可能有一个完整的文件。

FWIW,将自己限制为 8k 写入并不能拯救您,因为您现在依赖于底层操作系统和 FS 中的实现细节,这些细节可能在下一个版本中发生变化,或者在以前的版本中有所不同。

链接:

  1. http://83.139.107.116:8080/1.1/handlers/monodoc.ashx?link=M%3aMono.Unix.Native.Stdlib.rename(System.String%2cSystem.String)

Slight variation on Mark Byer's solution which I use all the time:

  1. Write new contents to a temp file IN THE SAME DIRECTORY as the file you want to replace.
  2. If the write is successful, rename[1] it to the desired file.

Rename is atomic so if it succeeds, then the system is not left in an undefined state. If it fails, then, again, the system is still in a pristine state AND you have a backup of the content you wanted to replace it with (in the temp file) on system restart.

My typical naming convention is along the lines of:

/path/to/original/content.data

/path/to/original/.#content.data

If the system shuts down somewhere in that process, on restart of your app, you can scan for .#content.data and either present that to the user as what they had been entering when the system went down or use some custom magic to decide whether or not it is "complete" to decide whether or not to rename it over content.data.

I don't know what kind of data you are writing so I can't help you decide what that "magic" would be, but if it's an xml file, for example, you could parse it for correctness and if you don't get an unexpected end-of-file, then you probably have a complete file.

FWIW, restricting yourself to 8k writes isn't going to save you because you are now depending on implementation details in the underlying OS and FS which could change in the next version or be different in a previous version.

Links:

  1. http://83.139.107.116:8080/1.1/handlers/monodoc.ashx?link=M%3aMono.Unix.Native.Stdlib.rename(System.String%2cSystem.String)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文