为什么我的文件有时会在阅读或写入的过程中消失



我有一个从文本文件读取的应用程序,以确定应生成哪些报告。它在大多数情况下都应起作用,但是该程序偶尔会删除从/写入读取的文本文件之一。然后,抛出一个例外("找不到文件"和进度停止。

这是一些相关的代码。

首先,从文件中读取:

List<String> delPerfRecords = ReadFileContents(DelPerfFile);
. . .
private static List<String> ReadFileContents(string fileName)
{
    List<String> fileContents = new List<string>();
    try
    {
        fileContents = File.ReadAllLines(fileName).ToList();
    }
    catch (Exception ex)
    {
        RoboReporterConstsAndUtils.HandleException(ex);
    }
    return fileContents;
}

然后,将其写入文件 - 它标记该文件中的记录/行已处理过,因此下次检查文件时不会重新生成相同的报告:

MarkAsProcessed(DelPerfFile, qrRecord);
. . .
private static void MarkAsProcessed(string fileToUpdate, string 
qrRecord)
{
    try
    {
        var fileContents = File.ReadAllLines(fileToUpdate).ToList();
        for (int i = 0; i < fileContents.Count; i++)
        {
            if (fileContents[i] == qrRecord)
            {
                fileContents[i] = string.Format("{0}{1} {2}"
qrRecord, RoboReporterConstsAndUtils.COMPLETED_FLAG, DateTime.Now);
            }
        }
        // Will this automatically overwrite the existing?
        File.Delete(fileToUpdate);
        File.WriteAllLines(fileToUpdate, fileContents);
    }
    catch (Exception ex)
    {
        RoboReporterConstsAndUtils.HandleException(ex);
    }
}

所以我确实删除了文件,但立即替换了文件:

File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);

所读取的文件具有这样的内容:

Opas,20170110,20161127,20161231-COMPLETED 1/10/2017 12:33:27 AM
Opas,20170209,20170101,20170128-COMPLETED 2/9/2017 11:26:04 AM
Opas,20170309,20170129,20170225-COMPLETED
Opas,20170409,20170226,20170401

if; quoted'出现在记录/行/行的末尾,它被忽略 - 不会处理。

另外,如果第二个元素(在索引1)是将来的日期,则不会对其进行处理。

因此,对于上面显示的这些示例,已经完成了前三个,随后将被忽略。第四个直到2017年4月9日或之后才能采取行动(此时将检索最后两个日期的数据范围内的数据)。

为什么有时会删除文件?我该怎么做才能防止这种情况发生?

如果有用,在更多情况下,逻辑就是这样:

internal static string GenerateAndSaveDelPerfReports()
{
    string allUnitsProcessed = String.Empty;
    bool success = false;
    try
    {
        List<String> delPerfRecords = ReadFileContents(DelPerfFile);
        List<QueuedReports> qrList = new List<QueuedReports>();
        foreach (string qrRecord in delPerfRecords)
        {
            var qr = ConvertCRVRecordToQueuedReport(qrRecord);
            // Rows that have already been processed return null
            if (null == qr) continue;
            // If the report has not yet been run, and it is due, add i
to the list
            if (qr.DateToGenerate <= DateTime.Today)
            {
                var unit = qr.Unit;
                qrList.Add(qr);
                MarkAsProcessed(DelPerfFile, qrRecord);
                if (String.IsNullOrWhiteSpace(allUnitsProcessed))
                {
                    allUnitsProcessed = unit;
                }
                else if (!allUnitsProcessed.Contains(unit))
                {
                    allUnitsProcessed = allUnitsProcessed + " and "  
unit;
                }
            }
        }
        foreach (QueuedReports qrs in qrList)
        {
            GenerateAndSaveDelPerfReport(qrs);
            success = true;
        }
    }
    catch
    {
        success = false;
    }
    if (success)
    {
        return String.Format("Delivery Performance report[s] generate
for {0} by RoboReporter2017", allUnitsProcessed);
    }
    return String.Empty;
}

如何熨烫此代码以防止文件定期丢弃?

更新

我无法真正测试这个问题,因为问题很少发生,但是我想知道是否添加了"暂停"在file.delete()和file.writealllines()之间解决问题?

之间

更新2

我不确定我的问题的答案是什么,所以我不会将其添加为答案,但是我的猜测是file.delete()and file.writealllines()出现太近了因此,删除有时会在文件的旧版本和新副本上发生。

如果是这样,两个呼叫之间的暂停可能已经解决了99.42%的时间,但是从我在这里发现的情况下,file.delete()似乎是多余的/多余的,所以我对此进行了测试。file.delete()发表了评论,效果很好;因此,我只是在没有那个偶尔有问题的电话的情况下做。我希望这能解决这个问题。

// Will this automatically overwrite the existing?
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);

我只需向WriteAllLines()添加一个额外的参数(默认为false)即可告诉该函数以覆盖模式打开文件,而根本不调用File.Delete()

您当前检查文件的返回值吗?


update :好的,看起来WriteAllLines()是.NET框架功能,因此无法更改,因此我删除了此答案。但是现在,这在评论中显示为另一个论坛上的建议解决方案:

"只需使用file.writealltext之类的东西,如果文件存在的位置, 数据刚刚被覆盖,如果文件不存在,则将是 创建。"

这正是我的意思(当时认为WriteAllLines()是用户定义的功能),因为我过去遇到了类似的问题。

因此,这样的解决方案可以解决一些棘手的问题(而不是删除/快速重新打开,只需覆盖文件) - 较少的操作系统工作,可能更少的文件/磁盘片段。

最新更新