gpt4 book ai didi

c# - 如何防止 System.IO.File.Open with FileMode.Truncate 导致文件更改

转载 作者:行者123 更新时间:2023-11-30 22:32:59 25 4
gpt4 key购买 nike

我有一个使用 XML 文件格式的应用程序。应用程序可以更改这些 XML 文件,但它还使用 System.IO.FileSystemWatcher 查看程序运行时 XML 文件是否在程序外部发生了更改。如果文件已更改,则应用程序会重新加载 XML 文件。

当然,如果应用程序保存 XML 文件,它会导致 Windows 检测到文件已更改,从而启动 FileSystemWatcher 事件。我不希望文件因为它已启动的更改而重新加载 XML 文件,因此每当它保存 XML 文件时,它都会记录特定文件更改时要忽略的次数。在应用程序中保存 XML 文件会增加计数。如果对文件的更改使用react会减少非零计数,或者如果计数已经为 0 则处理更改。

我遇到的问题是,当我保存 XML 文件时,我是这样做的:

Stream fileStream = null;

if(System.IO.File.Exists(fileToSave)
{
fileStream = System.IO.File.Open(fileName, FileMode.OpenOrCreate | FileMode.Truncate);
}
else
{
fs = System.IO.File.Open(fileName, FileMode.OpenOrCreate);
}
...

然后我使用 XmlWriter 将我的 XML 对象序列化到流中,然后关闭流。一切正常,除了这会导致我在 FileSystemWatcher 中的事件被引发两次。我花了一些时间进行调试,发现使用 Truncate 选项调用 System.IO.File.Open 实际上会更改磁盘上的文件。我在调用它后立即遇到断点,发现 XML 文件在磁​​盘上,大小为 0 字节。因此,似乎这种方法两次访问磁盘,导致我的 FileSystemWatcher 事件被引发两次。

我该如何解决这个问题?

作为解决方法,我发现我可以删除该文件(如果它存在),然后执行一个简单的 File.Open 而不使用 Truncate 选项,在我的情况下可以解决它......至少到目前为止。我假设这将启动 FileSystemWatcher 上的 Delete 事件。从技术上讲,我不想删除文件,如果我要在以后删除文件时添加特定的逻辑,这段代码可能会导致不正确地触发。

在不引起 2 FileSystemWatcher 事件的情况下更改现有文件的任何其他方法?

更新1

我问这个问题已经很多年了,文件监视系统已经成为我在 5 年前问这个问题以来一直使用和维护的应用程序的核心部分。

不幸的是,从那时起我仍然没有找到更好的解决方案来将 XML 序列化到磁盘而不导致 2 个文件监视更改。

对于 future 的读者,这是我正在使用的代码:

if (System.IO.File.Exists(fileName))
{
System.IO.File.Delete(fileName);
}

using( var fs = System.IO.File.Open(fileName, FileMode.OpenOrCreate))
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using(var writer = XmlWriter.Create(fs, settings))
{
// for info on this, see
// http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor
XmlSerializer serializer = XmlSerializer.FromTypes(new[] { type })[0];

serializer.Serialize(writer, objectToSerialize);

}
}

最佳答案

因此,您遇到的情况是目录中可能会发生更改,并且您希望您的程序对这些更改使用react。这本身是没有问题的。问题是您的程序无法判断是哪个进程在进行更改。因此,如果更改了该目录中的内容,那么您将陷入无限循环。

您为解决该问题而提出的任何方案都将是脆弱的,因为它会受到竞争条件的影响。您可以尝试设计一种方案,让您忽略您更改的文件的下 N 次更新通知,但在某些时候您会发现某些其他进程进行了您忽略的更新。

要做到这一点,唯一可靠的方法是有两个目录。您有一个 submissions 目录,客户端程序在其中添加文件。您的程序会监视该目录以进行添加。当客户端将文件添加到 submissions 时,您的程序会将文件移动到 repository 目录。客户端对 repository 目录具有只读访问权限。只有您的程序可以在存储库中添加、修改或删除文件。

关于c# - 如何防止 System.IO.File.Open with FileMode.Truncate 导致文件更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8515720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com