Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 锁定文件,同时保留在同一线程中读取/追加/写入/截断的功能?_C#_Windows_File Io - Fatal编程技术网

C# 锁定文件,同时保留在同一线程中读取/追加/写入/截断的功能?

C# 锁定文件,同时保留在同一线程中读取/追加/写入/截断的功能?,c#,windows,file-io,C#,Windows,File Io,粗略地说,我有一个包含应用程序状态的文件 我希望实现以下行为: 启动应用程序时,锁定文件,以便其他应用程序(或用户本身)无法修改它 从文件中读取以前的应用程序状态 。。。做工作 使用新状态更新文件(根据文件格式,需要重写整个文件;操作后文件长度可能会减少) 。。。做工作 再次更新该文件 。。。做工作 如果工作失败(应用程序崩溃),锁将被解除,文件内容将保持在前一个工作单元执行后的状态 似乎,要重写文件,应该使用Truncate选项打开它;这意味着每次要重写文件时,都应该打开一个新的FileS

粗略地说,我有一个包含应用程序状态的文件

我希望实现以下行为:

  • 启动应用程序时,锁定文件,以便其他应用程序(或用户本身)无法修改它
  • 从文件中读取以前的应用程序状态
  • 。。。做工作
  • 使用新状态更新文件(根据文件格式,需要重写整个文件;操作后文件长度可能会减少)
  • 。。。做工作
  • 再次更新该文件
  • 。。。做工作
  • 如果工作失败(应用程序崩溃),锁将被解除,文件内容将保持在前一个工作单元执行后的状态
似乎,要重写文件,应该使用
Truncate
选项打开它;这意味着每次要重写文件时,都应该打开一个新的
FileStream
。看来我想要的行为只能通过这样一种肮脏的方式来实现:

  • 当应用程序启动时,读取文件,然后
    FileShare.read打开
    FileStream
  • 完成某些工作后,关闭先前打开的句柄,用
    FileMode打开另一个
    FileStream
    。截断
    FileShare。读取
    ,写入数据并刷新
    FileStream
  • 完成某些工作后,关闭先前打开的句柄,用
    FileMode打开另一个
    FileStream
    。截断
    FileShare。读取
    ,写入数据并刷新
    FileStream
  • 在处置
  • 上,关闭先前打开的手柄
这种方式有一些缺点:额外的
FileStream
被打开;在
FileStream
关闭和
FileStream
打开之间,无法保证文件完整性;代码要复杂得多。
如果没有这些缺点,还有其他方法吗?

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


注意。

不要关闭并重新打开文件。相反,如果要重写文件,请使用(0)将其截断为零长度


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

您似乎误解了这个问题。我想在每个检查点上“更新磁盘上的文件”(这样,如果应用程序稍后崩溃,最新检查点之前的所有数据都将存储在磁盘上)。问题是:如何(多次)重写文件而不释放锁?事实上,问题与线程无关;我只是觉得用这种方式陈述问题会更容易理解。对不起,我被你问题的标题误导了。因此,您希望定期推送磁盘上的文件更新,但实际上不希望释放文件锁定,以便在进程运行时其他进程不应修改文件?是的,您是对的。此外,更新不是附加到现有文件,而是重写整个文件内容(以便新内容可能比原始内容短)。
FileStream.SetLength
正是我想要的!