【问题标题】:How to ensure c# finishes writing a file when program is stopped? [duplicate]程序停止时如何确保c#完成写入文件? [复制]
【发布时间】:2019-11-13 02:25:30
【问题描述】:

我有一个 c# 控制台应用程序,它经常快速地将大约 1-2mb 的数据写入文件(不断覆盖同一个文件)。然后我像这样在无限循环中运行程序

@echo off
:while
(
   C:\sync.exe
   goto :while
)

然后c#会这样写文本

    private static async Task WriteFile(string filePath, string text)
    {
        string base_path = AppDomain.CurrentDomain.BaseDirectory;
        string file_path = Path.Combine(base_path, filePath);
        using (StreamWriter outputFile = new StreamWriter(file_path))
        {
            await outputFile.WriteAsync(text);
        }
    }

但我注意到,当我使用 ctrl+c 结束程序或停止调试器时,当它处于写入过程中时,它会停止写入并使文件损坏并丢失数据。

有没有一种方法可以确保如果程序在写入过程中停止,它要么撤消更改(它会覆盖之前存在的文件),要么再次返回旧文件,或者它以某种方式完成写入(其中将需要不到一秒钟)?

【问题讨论】:

  • 当一个进程被杀死时,你无法阻止它,我知道。就像关闭计算机电源一样。
  • 没有。与机器失去动力没有什么不同。解决方法非常简单,写入一个临时文件并在完成后重命名它。重命名是原子的。
  • 是的,但是如果程序在删除旧文件和重命名新文件之间的某个地方结束怎么办?
  • 来吧,我们需要思考开箱即用的解决方案
  • 你忽略了好的建议,很难帮助你。当然,UPS 不会阻止程序意外终止。

标签: c# file-writing


【解决方案1】:

有没有一种方法可以确保如果程序在写入过程中停止,它要么撤消更改(它会覆盖之前存在的文件),要么再次返回旧文件,或者它以某种方式完成写入(其中将需要不到一秒钟)?

是的...写入不同的文件。写入完成后,使用Copy方法的this prototype复制文件,将第三个参数设置为true

private static async Task WriteFile(string filePath, string text)
{
    string temp_file = File.GetTempFileName();
    string base_path = AppDomain.CurrentDomain.BaseDirectory;
    using (StreamWriter outputFile = new StreamWriter(temp_file))
    {
        await outputFile.WriteAsync(text);
    }
    string file_path = Path.Combine(base_path, filePath);
    File.Copy(temp_file, file_path, true);
    File.Delete(temp_file);
}

【讨论】:

  • 但是如果程序在复制或删除时结束怎么办?
  • 这比使用 FileInfo.Replace() 更好吗?
  • 不,如果您愿意,可以使用 File.Replace 代替。如果您在单个文件操作的中间以某种方式中断程序(例如,如果您断电),那么您当然会被搞砸。没有办法解决这个问题(这就是为什么你的电脑有时会说“不要关闭你的电脑”——即使是微软的众神也无法解决这个限制)。如果这是一个关键任务文件,我建议永远不要覆盖它,并修改读取该文件的任何程序以搜索可用且完整的最新文件。
  • file.replace 在什么方面比这更好?顺便说一句,它的Path.GetTempFileName();
  • 我不确定这是不是真的。 NTFS 支持事务,但出于某种原因,Microsoft 建议在此用例中使用另一个名为 ReplaceFile 的 Win32 函数 - docs.microsoft.com/en-us/windows/win32/fileio/… 如果 .NET 中的替换方法使用此函数,则不太可能发生损坏,尤其是在程序被终止时。可能只有文件表中的指针会自动更新,因此即使电源故障也不会破坏这一点。不知道是不是这样,但总比抄袭好。
猜你喜欢
  • 1970-01-01
  • 2019-02-10
  • 2013-08-16
  • 2023-04-03
  • 1970-01-01
  • 2011-11-11
  • 1970-01-01
  • 2016-12-09
  • 2013-10-23
相关资源
最近更新 更多