2012-03-19 41 views
1

我有一个文件,粗略地说,包含应用程序的状态。锁定文件,同时保留在同一个线程中读取/附加/写入/截断的能力?

我要实现以下行为:

  • 当应用程序被启动,锁定文件,以使其他应用程序(或用户本身)将能够修改它;
  • 从文件读取以前的应用程序状态;
  • ...做的工作...
  • 更新一个新的状态文件(假定该文件的格式,包括重写整个文件,该文件的长度可能在手术后下降);
  • ...做的工作...
  • 再次更新文件
  • ...做的工作...
  • 如果工作失败(应用程序崩溃),锁被取下,并且内容的文件保持原先的工作单元执行后的状态。

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

  • 当应用程序被启动,读取该文件,然后打开FileStreamFileShare.Read;
  • 当一些工作完成后,关闭先前打开的手柄,打开另一个FileStreamFileMode.TruncateFileShare.Read,写入数据并刷新FileStream
  • 当一些工作完成后,关闭先前打开的手柄,打开另一个FileStreamFileMode.TruncateFileShare.Read,写入数据并刷新FileStream
  • Dispose,关闭句柄曾被打开。

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

回答

2

不要关闭并重新打开该文件。如果要重写它,请使用FileStream.SetLength(0)将文件截断为零。

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

+0

'FileStream.SetLength'正是我一直在寻找的! – penartur 2012-03-20 04:42:47

0

你为什么不采取独占模式访问文件应用程序启动时,并创建一个可以在所有线程的过程中,而你的实际文件保持锁定OS共享的文件在内存中缓存。您可以使用lock(memoryStream)来避免并发问题。当您完成更新文件的本地内存版本时,只需更新磁盘上的文件并释放锁定即可。

问候。

+0

看来你误解了这个问题。我想在每个_checkpoint_上“更新磁盘上的文件”(以便稍后应用程序崩溃时,直到最新检查点的所有数据都将存储在磁盘上)。问题是:我怎么能(多次)在不释放锁的情况下重写文件?事实上,这个问题与线程无关。我只是认为用这种方式表述这个问题会让人更容易理解。 – penartur 2012-03-19 07:34:32

+0

对不起,我误导了你的问题的标题。所以您想要定期将更新推送到磁盘上的文件,但实际上并不想释放文件上的锁定,以便在进程运行时其他进程不应该修改该文件? – 2012-03-19 07:48:54

+0

是的,你是对的。此外,_update_不是附加到现有文件,而是重写整个文件内容(以便新内容可能比原始内容短)。 – penartur 2012-03-19 09:28:18

相关问题