我的应用程序在自助服务终端(C#/ WPF)中的独立面板PC上运行。它对文本文件执行一些典型的日志记录操作。 PC具有一些有限的磁盘空间来存储这些日志。
我需要做的是能够指定允许日志文件的最大大小。如果在尝试写入日志时超出最大大小,则新数据将写入日志末尾,并且最早的数据将从头开始清除。
获取文件大小没问题,但有没有任何典型的文件操作技术可以将文件保持在一定的大小?
答案 0 :(得分:15)
处理此问题的一种方法是拥有两个日志文件,每个日志文件的最大大小的一半。当您达到每个文件的最大大小时,您只需在两者之间旋转。旋转到文件会导致它被新文件覆盖。
日志框架(如log4net)内置了此功能。
答案 1 :(得分:5)
答案 2 :(得分:4)
从文件开头剥离数据没有简单的方法。所以你有几个选择:
答案 3 :(得分:2)
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/
答案 4 :(得分:0)
我不会将它用于一个超过1兆的文件并且效率不高,但是如果你需要解决一个棘手的问题需要一个日志文件它会很好用你不能方便地维护。在使用之前确保日志文件存在...或者您可以为其添加代码以及检查位置是否存在等。
// 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);
}
}
}
答案 5 :(得分:0)
我也想要一个简单的解决方案,但是我不想添加另一个依赖关系,所以我做了一个简单的方法。除了将旧文件压缩为zip之外,它还具有其他所需的一切,您可以在此处找到:Create zip file in memory from bytes (text with arbitrary 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);
}
}