使用C#.NET 4.0修剪简单的文本日志文件

本文关键字:文本 日志 文件 简单 修剪 NET 使用 | 更新日期: 2023-09-27 17:59:30

我使用的一个外部Windows服务维护一个基于文本的日志文件,它会不断地将其附加到该文件中。随着时间的推移,该日志文件会无限增长。我想定期修剪这个日志文件来维护,比如说最近的5mb日志条目。如何在C#.NET 4.0中高效地实现文件I/O代码,将文件修剪为5mb?

更新时间:按照设置服务依赖关系的方式,我的服务总是在外部服务之前启动。这意味着如果需要,我可以独占访问日志文件以截断它。一旦外部服务启动,我将不会访问日志文件。我可以在桌面启动时获得对该文件的独占访问权限。问题是,日志文件的大小可能只有几GB,我正在寻找一种有效的方法来截断它。

使用C#.NET 4.0修剪简单的文本日志文件

处理"新"日志文件需要存储大量内存,但如果只需要5Mb,则应该可以。如果您谈论的是Gb+,那么您可能还有其他问题;然而,它仍然可以使用临时文件和一些锁定来完成。

如前所述,您可能会遇到竞争条件,但如果这是唯一一个写入该文件的线程,则情况并非如此。这将替换您当前对文件的写入。

const int MAX_FILE_SIZE_IN_BYTES = 5 * 1024 * 1024; //5Mb;
const string LOG_FILE_PATH = @"ThisFolder'log.txt";
string newLogMessage = "Hey this happened";

#region Use one or the other, I mean you could use both below if you really want to.
//Use this one to save an extra character
if (!newLogMessage.StartsWith(Environment.NewLine))
    newLogMessage = Environment.NewLine + newLogMessage;
//Use this one to imitate a write line
if (!newLogMessage.EndsWith(Environment.NewLine))
    newLogMessage = newLogMessage + Environment.NewLine; 
#endregion
int newMessageSize = newLogMessage.Length*sizeof (char);
byte[] logMessage = new byte[MAX_FILE_SIZE_IN_BYTES];
//Append new log to end of "file"
System.Buffer.BlockCopy(newLogMessage.ToCharArray(), 0, logMessage, MAX_FILE_SIZE_IN_BYTES - newMessageSize, logMessage.Length);

FileStream logFile = File.Open(LOG_FILE_PATH, FileMode.Open, FileAccess.ReadWrite);
int sizeOfRetainedLog = (int)Math.Min(MAX_FILE_SIZE_IN_BYTES - newMessageSize, logFile.Length);
//Set start position/offset of the file
logFile.Position = logFile.Length - sizeOfRetainedLog;
//Read remaining portion of file to beginning of buffer
logFile.Read(logMessage, logMessage.Length, sizeOfRetainedLog);
//Clear the file
logFile.SetLength(0); 
logFile.Flush();
//Write the file
logFile.Write(logMessage, 0, logMessage.Length);

我写得很快,如果我1点前离开某个地方,我道歉。

根据写入的频率,我认为您可能面临在不损坏日志的情况下修改文件的竞争条件。你可以尝试编写一个服务来监控文件大小,一旦达到某个点,就锁定文件,复制并清除整个文件,然后关闭它。然后将数据存储在另一个文件中,该服务可以轻松控制文件大小。或者,您可以查看外部服务是否有登录数据库的选项,这将使推出最旧的数据变得非常简单。

您可以使用文件观察器来监视文件:

FileSystemWatcher logWatcher = new FileSystemWatcher();
        logWatcher.Path = @"c:'example.log"
        logWatcher.Changed += logWatcher_Changed;

然后,当事件发生时,您可以使用StreamReader读取文件

private void logWatcher_Changed(object sender, FileSystemEventArgs e)
    {
     using (StreamReader readFile = new StreamReader(path))
        {
            string line;
            string[] row;
            while ((line = readFile.ReadLine()) != null)
            {
               // Here you delete the lines you want or move it to another file, so that your log keeps small. Then save the file. 
            }
        }
    }

这是一种选择。