我有一个在信息亭 (C#/WPF) 中的独立面板 PC 上运行的应用程序。它对文本文件执行一些典型的日志记录操作。随着日志的增长,PC 有一些有限的磁盘空间来存储这些日志。
我需要做的是能够指定日志文件允许的最大大小。如果在尝试写入日志时超过了最大大小,则新数据将被写入日志的末尾,而最旧的数据将从头开始清除。
获取文件大小是没有问题的,但是是否有任何典型的文件操作技术可以将文件保持在一定大小以下?
我有一个在信息亭 (C#/WPF) 中的独立面板 PC 上运行的应用程序。它对文本文件执行一些典型的日志记录操作。随着日志的增长,PC 有一些有限的磁盘空间来存储这些日志。
我需要做的是能够指定日志文件允许的最大大小。如果在尝试写入日志时超过了最大大小,则新数据将被写入日志的末尾,而最旧的数据将从头开始清除。
获取文件大小是没有问题的,但是是否有任何典型的文件操作技术可以将文件保持在一定大小以下?
处理此问题的一种技术是拥有两个日志文件,每个文件的大小为最大大小的一半。当您达到每个文件的最大大小时,您只需在两者之间旋转。旋转到一个文件会导致它被一个新文件覆盖。
诸如 log4net 之类的日志框架内置了此功能。
尝试使用 Log4Net
没有简单的方法可以从文件开头剥离数据。所以你有几个选择:
Linux 操作系统:查看 logrotate - http://www.cyberciti.biz/faq/how-do-i-rotate-log-files/
Windows 操作系统:尝试使用谷歌搜索 windows logrotate。例如:http ://blog.arithm.com/2008/02/07/windows-log-file-rotation/
我不会将它用于意味着超过 1 Meg 的文件,而且它的效率不是很高,但是如果您需要解决一个讨厌的问题,即您需要一个无法方便维护的日志文件时,它会很好用。在使用它之前确保日志文件存在......或者你可以为它添加代码以及检查位置是否存在等。
// This is how to call it
private void buttonLog_Click(object sender, EventArgs e)
{
c_Log.writeToFile(textBoxMessages.Text, "../../log.log", 1);
}
public static class c_Log
{
static int iMaxLogLength = 15000; // Probably should be bigger, say 200,000
static int iTrimmedLogLength = -1000; // minimum of how much of the old log to leave
static public void writeToFile(string strNewLogMessage, string strFile, int iLogLevel)
{
try
{
FileInfo fi = new FileInfo(strFile);
Byte[] bytesSavedFromEndOfOldLog = null;
if (fi.Length > iMaxLogLength) // if the log file length is already too long
{
using (BinaryReader br = new BinaryReader(File.Open(strFile, FileMode.Open)))
{
// Seek to our required position of what you want saved.
br.BaseStream.Seek(iTrimmedLogLength, SeekOrigin.End);
// Read what you want to save and hang onto it.
bytesSavedFromEndOfOldLog = br.ReadBytes((-1 * iTrimmedLogLength));
}
}
byte[] newLine = System.Text.ASCIIEncoding.ASCII.GetBytes(Environment.NewLine);
FileStream fs = null;
// If the log file is less than the max length, just open it at the end to write there
if (fi.Length < iMaxLogLength)
fs = new FileStream(strFile, FileMode.Append, FileAccess.Write, FileShare.Read);
else // If the log file is more than the max length, just open it empty
fs = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read);
using (fs)
{
// If you are trimming the file length, write what you saved.
if (bytesSavedFromEndOfOldLog != null)
{
Byte[] lineBreak = Encoding.ASCII.GetBytes("### " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " *** *** *** Old Log Start Position *** *** *** *** ###");
fs.Write(newLine, 0, newLine.Length);
fs.Write(newLine, 0, newLine.Length);
fs.Write(lineBreak, 0, lineBreak.Length);
fs.Write(newLine, 0, newLine.Length);
fs.Write(bytesSavedFromEndOfOldLog, 0, bytesSavedFromEndOfOldLog.Length);
fs.Write(newLine, 0, newLine.Length);
}
Byte[] sendBytes = Encoding.ASCII.GetBytes(strNewLogMessage);
// Append your last log message.
fs.Write(sendBytes, 0, sendBytes.Length);
fs.Write(newLine, 0, newLine.Length);
}
}
catch (Exception ex)
{
; // Nothing to do...
//writeEvent("writeToFile() Failed to write to logfile : " + ex.Message + "...", 5);
}
}
}
我也想要一个简单的解决方案,但我不想添加另一个依赖项,所以我做了一个简单的方法。除了将旧文件压缩为 zip 的部分之外,这包含您需要的一切,您可以在此处找到:Create zip file in memory from bytes (text with random encoding)
static int iMaxLogLength = 2000; // Probably should be bigger, say 200,000
static int KeepLines = 5; // minimum of how much of the old log to leave
public static void ManageLogs(string strFileName)
{
try
{
FileInfo fi = new FileInfo(strFileName);
if (fi.Length > iMaxLogLength) // if the log file length is already too long
{
int TotalLines = 0;
var file = File.ReadAllLines(strFileName);
var LineArray = file.ToList();
var AmountToCull = (int)(LineArray.Count - KeepLines);
var trimmed = LineArray.Skip(AmountToCull).ToList();
File.WriteAllLines(strFileName, trimmed);
string archiveName = strFileName + "-" + DateTime.Now.ToString("MM-dd-yyyy") + ".zip";
File.WriteAllBytes(archiveName, Compression.Zip(string.Join("\n", file)));
}
}
catch (Exception ex)
{
Console.WriteLine("Failed to write to logfile : " + ex.Message);
}
}
我将此作为我的应用程序的初始化/重新初始化部分的一部分,因此它每天运行几次。
ErrorLogging.ManageLogs("Application.log");