10

私の C# winforms 4.0 アプリケーションは、スレッドセーフなストリームライターを使用して、内部のデバッグ ログ情報を処理しています。私のアプリが開くと、ファイルが削除され、再作成されます。アプリを閉じると、ファイルが保存されます。

私がしたいのは、置き換えではなく追加を行うようにアプリケーションを変更することです。これは簡単な修正です。

ただし、ここに私の質問があります:

ログ ファイルを最大で 10 メガバイト前後に維持したいと考えています。私の制約は単純です。ファイルを閉じるときに、ファイルが 10 メガバイトを超える場合は、最初の 10% を切り捨てます。

次のことを行う「より良い」方法はありますか:

  1. ファイルを閉じる
  2. ファイルが 10 MB を超えているかどうかを確認します
  3. その場合は、ファイルを開きます
  4. 全体をパースする
  5. 最初の 10% を選別する
  6. ファイルを書き戻す
  7. 近い

編集:まあ、私は自分自身をロールバックしました(以下に示されています)明白にLog4Netに移行するという提案は良いものですが、新しいライブラリを学び、すべてのログステートメント(数千)を移行するのにかかる時間はそうではありません.私が行おうとしていた小さな強化に有効な時間。

  private static void PerformFileTrim(string filename)
  {
     var FileSize = Convert.ToDecimal((new System.IO.FileInfo(filename)).Length);

     if (FileSize > 5000000)
     {
        var file = File.ReadAllLines(filename).ToList();
        var AmountToCull = (int)(file.Count * 0.33); 
        var trimmed = file.Skip(AmountToCull).ToList();
        File.WriteAllLines(filename, trimmed);
     }
  }
4

6 に答える 6

2

これは、bigtech の回答から派生したものです。

private static string RollLogFile()
    {
        string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        string appName = Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]);
        string wildLogName = string.Format("{0}*.log",appName);

        int fileCounter = 0;
        string[] logFileList = Directory.GetFiles(path, wildLogName, SearchOption.TopDirectoryOnly);
        if (logFileList.Length > 0)
        {
            Array.Sort(logFileList, 0, logFileList.Length);
            fileCounter = logFileList.Length - 1;
            //Make sure we apply the MaxLogCount (but only once to reduce the delay) 
            if (logFileList.Length > MaxLogCount)
            {
                //Too many files - remove one and rename the others
                File.Delete(logFileList[0]);
                for (int i = 1; i < logFileList.Length; i++)
                {
                    File.Move(logFileList[i], logFileList[i - 1]); 
                }
                --fileCounter;
            }

            string currFilePath = logFileList[fileCounter];
            FileInfo f = new FileInfo(currFilePath);
            if (f.Length < MaxLogSize)
            {
                //still room in the current file
                return currFilePath;
            }
            else
            {
                //need another filename
                ++fileCounter;                  
            }

        }
        return string.Format("{0}{1}{2}{3:00}.log", path, Path.DirectorySeparatorChar, appName, fileCounter);
    }

使用法:

string logFileName = RollLogFile();
using (StreamWriter sw = new StreamWriter(logFileName, true))
{
    sw.AutoFlush = true;
    sw.WriteLine(string.Format("{0:u} {1}", DateTime.Now, message));
}
于 2015-03-17T20:55:18.117 に答える
1

私はwin32 APIを調べていましたが、ネイティブのwin32 vfs呼び出しでこれを行うことができるかどうかさえわかりません.Netを気にする必要はありません。

私が持っている唯一の解決策は、メモリマップファイルを使用してデータを手動で移動することです.Netは.Net 4.0の時点でサポートしているようです。

メモリ マップト ファイル

于 2013-06-05T21:39:20.613 に答える