【问题标题】:How do I delete a file that was opened by xmlreader in c#?如何删除由 xmlreader 在 C# 中打开的文件?
【发布时间】:2013-02-05 23:07:59
【问题描述】:

我研究了几个问题,但我找到的答案都没有帮助。此函数的目标是修改 xml 文件。我读取原始文件并将旧的东西和新的东西写入新文件。所有这一切都完美无缺。当我完成并需要删除旧文件并移动新文件时出现问题。

收到的错误是 jnv_config.xml 正在被另一个进程(阅读器文件)使用。

移除 Close 和/或 Dispose 并不能解决问题。

using (XmlReader reader = XmlReader.Create("jnv_config.xml"))
using (XmlWriter writer = XmlWriter.Create("jnv_temp.xml"))
{
    writer.WriteStartDocument();
    while (reader.Read())
    {
      // Read the file, write to the other file - this part works perfectly.
      // No filestreams nor anything else is created in here.
    }
    writer.WriteEndElement();
    writer.WriteEndDocument();
    reader.Close();
    writer.Close();
    reader.Dispose();
    writer.Dispose();
}
// Delete the old file and copy the new one
File.Delete("jnv_config.xml");
//File.Move("jnv_temp.xml", "jnv_config.xml");

我正在使用 VS2012 (NET 4.5)、C#、标准 Windows 窗体项目。

【问题讨论】:

  • 由于您有using 关键字,您不必调用reader.Dispose()writer.Dispose()。一旦超出范围(在using 之外),它们将被发送到Garbage Collection
  • 出于好奇,为什么要将 XML 从一个文件复制到另一个文件,然后删除原始文件并将新文件重命名为原始文件?这不是无操作吗?
  • @BennorMcCarthy 我假设 CramerTV 的实际代码确实更改了 XML,但这是一个简化版本,只是演示了问题。
  • @BennorMcCarthy,如果用户更改了应用程序配置中的某些内容,我会更改配置文件以反映这些更改。我评论的重点是确保人们理解我没有创建任何可能使文件描述符保持打开状态的新对象。
  • 是的,我认为可能是这样。

标签: c# xml winforms xmlreader


【解决方案1】:

您确定是这个XmlReader 仍然打开了文件吗?您是否尝试过在此代码执行之前使用Process Explorer 确认配置文件没有打开的文件句柄?

【讨论】:

  • 您说得对,先生。我在另一个函数中打开了文件,而没有使用“使用”结构。干得好。
【解决方案2】:

在删除文件之前检查文件是否准备就绪。如果您处理大文件,可能会通过循环调用代码几秒钟。

private void IsFileOpen(FileInfo file)
{
    FileStream stream = null;
    try {
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (Exception ex) {

        if (ex is IOException && IsFileLocked(ex)) {
            // do something here, either close the file if you have a handle or as a last resort terminate the process - which could cause corruption and lose data
        }
    }
}

private static bool IsFileLocked(Exception exception)
{
    int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1);
    return errorCode == 32 || errorCode == 33;
}

【讨论】:

    【解决方案3】:

    根据我的经验,许多 NTFS 文件处理函数(尤其是 DELETE)是略微异步的。尝试在重命名之前添加睡眠或等待至少 0.2 秒。


    由于这不起作用,我建议将 Sleep/Wait 放在之前,然后慢慢增加它直到它起作用。如果你达到了一些不合理的大时间跨度(比如 10 秒)并且它仍然不起作用,那么我认为你可以公平地得出结论,问题是你 XmlReader 没有被释放只要你留在这个代码。

    在这种情况下,您可能需要做一些事情来确保它被完全处置,例如强制 GC 运行。

    【讨论】:

    • 感谢您的建议。它实际上是在 delete 调用本身上引发异常。我确实尝试在删除前后延迟,但没有任何乐趣。
    • 为什么不将代码包装在 try catch 周围并正确捕获异常..?如果您没有传递文件路径..,它如何知道该文件的位置在哪里?您不能从加载 .XML 文件的位置捕获它吗?您还需要在关闭和/或 Disposing 之前 Flush() 文件吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2017-05-03
    相关资源
    最近更新 更多