0

どのレポートを生成する必要があるかを判断するためにテキスト ファイルから読み取るアプリがあります。ほとんどの場合は正常に動作しますが、時々、プログラムが読み書きするテキスト ファイルの 1 つを削除することがあります。その後、例外がスローされ (「ファイルが見つかりませんでした」)、進行が停止します。

ここにいくつかの関連コードがあります。

まず、ファイルから読み取ります。

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」が表示されている場合、無視されます - 処理されません。

また、2 番目の要素 (インデックス 1) が将来の日付である場合、(まだ) 処理されません。

したがって、上記の例では、最初の 3 つが既に実行されており、以降は無視されます。4 番目のものは、2017 年 4 月 9 日以降まで処理されません (この時点で、最後の 2 つの日付のデータ範囲内のデータが取得されます)。

ファイルが時々削除されるのはなぜですか? それが起こらないようにするにはどうすればよいですか?

役立つ場合、より多くのコンテキストで、ロジックは次のようになります。

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() が近すぎて発生していたので、ファイルの古いコピーと新しいコピーの両方で削除が発生することがありました。

もしそうなら、2 つの呼び出しの間の一時停止は 99.42% の時間で問題を解決したかもしれませんが、私がここで見つけたものから、File.Delete() はとにかく冗長/余分であるように見えるので、File.Delete でテストしました() がコメントアウトされ、問題なく動作しました。だから、私は今、時折問題となる電話をせずにやっています。それが問題を解決することを期待しています。

4

1 に答える 1

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

WriteAllLines()追加のパラメーターを(デフォルトで) に追加するだけfalseで、ファイルを上書きモードで開くように関数に指示し、File.Delete()その後はまったく呼び出さないようにします。

現在、開いているファイルの戻り値を確認していますか?


更新:わかりWriteAllLines()ました。.Net Framework 関数のように見えるため、変更できないため、この回答を削除しました。ただし、これは別のフォーラムで提案された解決策として、コメントに表示されます。

「ファイルが存在する場合はデータが上書きされ、ファイルが存在しない場合は作成される File.WriteAllText のようなものを使用するだけです。」

過去に同様の問題があったため、これはまさに私が意図したことWriteAllLines()でした (思考はユーザー定義関数でしたが)。

したがって、そのようなソリューションは、いくつかのトリッキーな問題を解決する可能性があります (削除/高速再オープンではなく、ファイルを上書きするだけです)-OS の作業も少なくなり、ファイル/ディスクの断片化も少なくなる可能性があります。

于 2017-03-15T22:11:10.993 に答える