gpt4 book ai didi

c# - System.IO.File.Delete()/System.IO.File.Move() 有时不起作用

转载 作者:太空狗 更新时间:2023-10-29 22:09:49 25 4
gpt4 key购买 nike

Winforms 程序需要将一些运行时信息保存到 XML 文件中。该文件有时可能有几百 KB 的大小。在 Beta 测试期间,我们发现一些用户会毫不犹豫地终止进程,看似随意,偶尔会导致文件写入一半并因此损坏。

因此,我们更改了算法以保存到临时文件,然后删除真实文件并进行 move 。

我们的代码目前看起来是这样的..

private void Save()
{
XmlTextWriter streamWriter = null;
try
{
streamWriter = new XmlTextWriter(xmlTempFilePath, System.Text.Encoding.UTF8);

XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyCollection));

xmlSerializer.Serialize(streamWriter, myCollection);

if (streamWriter != null)
streamWriter.Close();

// Delete the original file
System.IO.File.Delete(xmlFilePath);

// Do a move over the top of the original file
System.IO.File.Move(xmlTempFilePath, xmlFilePath);
}
catch (System.Exception ex)
{
throw new InvalidOperationException("Could not save the xml file.", ex);
}
finally
{
if (streamWriter != null)
streamWriter.Close();
}
}

这几乎在所有时间都适用于实验室和生产。该程序在 12 台计算机上运行,​​这段代码平均每 5 分钟调用一次。大约一天一次或两次,我们会收到此异常:

System.InvalidOperationException: 
Could not save the xml file.
---> System.IO.IOException: Cannot create a file when that file already exists.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.__Error.WinIOError()
at System.IO.File.Move(String sourceFileName, String destFileName)
at MyApp.MyNamespace.InternalSave()

就好像在Move发出之前Delete实际上并没有下达到硬盘上。

这发生在 Win7 机器上。

几个问题:是否有一些Flush() 的概念可以用于整个磁盘操作系统?这是我的代码、.net、操作系统或其他东西的错误吗?我应该加入一些 Thread.Sleep(x) 吗?也许我应该做一个 File.Copy(src, dest, true)?我应该写下面的代码吗? (但它看起来很傻。)

while (System.IO.File.Exists(xmlFilePath))
{
System.IO.File.Delete(xmlFilePath);
}

// Do a move over the top of the main file
bool done = false;
while (!done)
{
try
{
System.IO.File.Move(xmlTempFilePath, xmlFilePath);
done = true;
}
catch (System.IO.IOException)
{
// let it loop
}
}

有人见过这个吗?

最佳答案

您永远不能假设您可以删除文件并在多用户多任务操作系统上删除它。除了另一个应用程序或用户自己对文件感兴趣之外,您还可以运行对文件感兴趣的服务。病毒扫描程序和搜索索引器是典型的麻烦制造者。

此类程序打开文件并尝试通过指定删除共享访问权限来尽量减少影响。这在 .NET 中也可用,它是 FileShare.Delete 选项。有了这个选项,Windows 允许进程删除文件,即使它是打开的。它在内部被标记为“删除待处理”。该文件实际上并没有从文件系统中删除,它在 File.Delete 调用之后仍然存在。之后尝试打开文件的任何人都会收到拒绝访问错误。在文件对象的最后一个句柄关闭之前,文件实际上并没有被删除。

您可能会看到这是标题,这解释了为什么 File.Delete 成功但 File.Move 失败。您需要做的是 File.Move 文件,使其具有不同的名称。 然后重命名新文件,然后删除原来的文件。您要做的第一件事是删除一个可能的重命名名称的杂散副本,它可能是由于电源故障而遗留下来的。

总结:

  1. 新建文件.new
  2. 删除文件.tmp
  3. 将 file.xml 重命名为 file.tmp
  4. 将 file.new 重命名为 file.xml
  5. 删除文件.tmp

第 5 步的失败并不重要。

关于c# - System.IO.File.Delete()/System.IO.File.Move() 有时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6466940/

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