【问题标题】:Lock a file while retaining the ability to read/append/write/truncate in the same thread?锁定文件,同时保留在同一个线程中读取/追加/写入/截断的能力?
【发布时间】:2012-03-19 04:35:38
【问题描述】:

我有一个文件,大致包含应用程序的状态。

我想实现以下行为:

  • 应用程序启动时,锁定文件,使其他应用程序(或用户本身)无法修改它;
  • 从文件中读取之前的应用程序状态;
  • ...做工作...
  • 使用新状态更新文件(根据文件的格式,这涉及重写整个文件;操作后文件的长度可能会减少);
  • ...做工作...
  • 再次更新文件
  • ...做工作...
  • 如果工作失败(应用程序崩溃),则解除锁定,文件的内容将保持上一个工作单元执行后的状态。

看来,要重写文件,应该使用Truncate 选项打开它;这意味着人们每次想要重写文件时都应该打开一个新的FileStream。所以看来我想要的行为只能通过这种肮脏的方式来实现:

  • 应用程序启动后,读取文件,然后FileShare.Read打开FileStream
  • 完成一些工作后,关闭之前打开的句柄,用FileMode.TruncateFileShare.Read打开另一个FileStream,写入数据并刷新FileStream
  • 完成一些工作后,关闭之前打开的句柄,用FileMode.TruncateFileShare.Read打开另一个FileStream,写入数据并刷新FileStream
  • Dispose 上,关闭之前打开的句柄。

这种方式有一些缺点:打开了额外的FileStream;在FileStream close 和FileStream open 之间不能保证文件的完整性;代码要复杂得多。 有没有其他方法,没有这些缺点?

【问题讨论】:

    标签: c# windows file-io


    【解决方案1】:

    不要关闭并重新打开文件。相反,当您想重写文件时,请使用FileStream.SetLength(0) 将文件截断为零长度。

    您可能(或可能不需要)还需要将 FileStream.Position 设置为零。文档没有说明 SetLength 是否移动文件指针。

    【讨论】:

    • FileStream.SetLength 正是我想要的!
    【解决方案2】:

    为什么不在应用程序启动时对文件进行独占访问,并为该文件创建一个内存缓存,该缓存可以在进程中的所有线程之间共享,而您的实际文件仍然为操作系统锁定。您可以使用 lock(memoryStream) 来避免并发问题。当您完成更新文件的本地内存版本时,只需更新磁盘上的文件并释放它的锁定。

    问候。

    【讨论】:

    • 看来你误解了这个问题。我想在每个 checkpoint 上“更新磁盘上的文件”(这样如果应用程序稍后崩溃,直到最新检查点的所有数据都将存储在磁盘上)。问题是:我如何(多次)重写文件而不释放锁?事实上,问题与线程无关。我只是认为以这种方式陈述问题会更容易理解。
    • 对不起,我被你的问题的标题误导了。所以你想定期推送更新到磁盘上的文件,但实际上不想释放文件的锁定,以便其他进程在你的进程运行时不应该修改文件?
    • 是的,你是对的。此外,update 不是附加到现有文件,而是重写整个文件内容(因此新内容可能比原始内容短)。
    猜你喜欢
    • 1970-01-01
    • 2018-11-14
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多