簡體   English   中英

為什么我的文件有時在讀取或寫入過程中消失?

[英]Why does my file sometimes disappear in the process of reading from it or writing to it?

我有一個可以從文本文件中讀取內容的應用程序,以確定應該生成哪些報告。 它在大多數情況下都應能正常工作,但有時會刪除該程序,該程序會從中讀取/寫入其中的一個文本文件。 然后引發異常(“找不到文件”),並且進程停止。

這是一些相關的代碼。

首先,從文件中讀取:

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

如果“ -COMPLETED”出現在記錄/行/行的末尾,則將被忽略-將不被處理。

同樣,如果第二個元素(在索引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()和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()

您當前是否檢查打開的文件的返回值?


更新 :好的,看來WriteAllLines()是.Net Framework函數,因此無法更改,因此我刪除了此答案。 但是,現在這已顯示在評論中,作為另一個論壇上的建議解決方案:

“只要使用File.WriteAllText之類的文件,如果文件存在,則數據將被覆蓋,如果文件不存在,則將創建它。”

這正是我的意思(認為WriteAllLines()是用戶定義的函數),因為過去我也遇到過類似的問題。

因此,類似的解決方案可以解決一些棘手的問題(而不是刪除/快速重新打開,而只是覆蓋文件)-減少OS的工作量,並可能減少文件/磁盤碎片。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM