我使用的外部Windows服务维护一个连续附加的基于文本的日志文件。随着时间的推移,此日志文件无限增长。我想定期修剪这个日志文件来维护,比如最近的5mb日志条目。如何在C#.NET 4.0中有效地实现文件I / O代码以将文件修剪为5mb?
更新: 设置服务依赖关系的方式,我的服务总是在外部服务之前启动。这意味着如果需要,我可以独占访问日志文件以截断它。外部服务启动后,我将无法访问日志文件。我可以在桌面启动时获得对该文件的独占访问权限。问题是 - 日志文件的大小可能只有几千兆字节,我正在寻找一种截断它的有效方法。
答案 0 :(得分:1)
您需要存储的内存量来处理“新”日志文件,但如果您只想要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 :(得分:0)
取决于它写入的频率我会说你可能面临竞争条件来修改文件而不损坏日志。您可以随时尝试编写服务来监视文件大小,一旦达到某个点就锁定文件,重复并清除整个文件并关闭它。然后将数据存储在服务控制大小的另一个文件中。或者,您可以查看外部服务是否具有用于记录到数据库的选项,这样可以非常简单地推出最旧的数据。
答案 2 :(得分:0)
您可以使用文件观察器来监控文件:
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.
}
}
}
这是一个选择。