Using StreamWriter to implement a rolling log, and deleting from top

greggorob64 picture greggorob64 · Jun 5, 2013 · Viewed 10.7k times · Source

My C# winforms 4.0 application has been using a thread-safe streamwriter to do internal, debug logging information. When my app opens, it deletes the file, and recreates it. When the app closes, it saves the file.

What I'd like to do is modify my application so that it does appending instead of replacing. This is a simple fix.

However, here's my question:

I'd like to keep my log file AROUND 10 megabytes maximum. My constraint would be simple. When you go to close the file, if the file is greater than 10 megabytes, trim out the first 10%.

Is there a 'better' way then doing the following:

  1. Close the file
  2. Check if the file is > 10 meg
  3. If so, open the file
  4. Parse the entire thing
  5. Cull the first 10%
  6. Write the file back out
  7. Close

Edit: well, I ended up rolling my own (shown following) the suggestion to move overt to Log4Net is a good one, but the time it woudl take to learn the new library and move all my log statements (thousands) over isn't time effective for the small enhancement I was trying to make.

  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);
     }
  }

Answer

bigtech picture bigtech · Jun 6, 2013

I researched this once and never came up with anything, but I can offer you plan B here:

I use the selection below to keep a maximum of 3 log files. At first, log file 1 is created and appended to. When it exceeds maxsize, log 2 and later log 3 are created. When log 3 is too large, log 1 is deleted and the remaining logs get pushed down the stack.

string[] logFileList = Directory.GetFiles(Path.GetTempPath(), "add_all_*.log", SearchOption.TopDirectoryOnly);
if (logFileList.Count() > 1)
{
    Array.Sort(logFileList, 0, logFileList.Count());
}

if (logFileList.Any())
{
    string currFilePath = logFileList.Last();
    string[] dotSplit = currFilePath.Split('.');
    string lastChars = dotSplit[0].Substring(dotSplit[0].Length - 3);
    ctr = Int32.Parse(lastChars);
    FileInfo f = new FileInfo(currFilePath);

    if (f.Length > MaxLogSize)
    {
        if (logFileList.Count() > MaxLogCount)
        {
            File.Delete(logFileList[0]);
            for (int i = 1; i < MaxLogCount + 1; i++)
            {
                Debug.WriteLine(string.Format("moving: {0} {1}", logFileList[i], logFileList[i - 1]));
                File.Move(logFileList[i], logFileList[i - 1]); // push older log files back, in order to pop new log on top
            }
        }
        else
        {
            ctr++;
        }
    }
}