将日志文件保持在一定大小

时间:2011-01-19 21:34:39

标签: c# file logging filesize file-manipulation

我的应用程序在自助服务终端(C#/ WPF)中的独立面​​板PC上运行。它对文本文件执行一些典型的日志记录操作。 PC具有一些有限的磁盘空间来存储这些日志。

我需要做的是能够指定允许日志文件的最大大小。如果在尝试写入日志时超出最大大小,则新数据将写入日志末尾,并且最早的数据将从头开始清除。

获取文件大小没问题,但有没有任何典型的文件操作技术可以将文件保持在一定的大小?

6 个答案:

答案 0 :(得分:15)

处理此问题的一种方法是拥有两个日志文件,每个日志文件的最大大小的一半。当您达到每个文件的最大大小时,您只需在两者之间旋转。旋转到文件会导致它被新文件覆盖。

日志框架(如log4net)内置了此功能。

答案 1 :(得分:5)

答案 2 :(得分:4)

从文件开头剥离数据没有简单的方法。所以你有几个选择:

  1. 如果所有日志文件的总大小超出限制,请将日志保留在几个较小的日志文件中并删除最旧的“块”。这类似于你想要做的,但在不同的层面上
  2. 将日志文件重命名为“log.date”并启动新日志。与(1)类似,但如果磁盘空间有限,则不能选择。
  3. 如果你有足够的内存并且你的日志大小相对较小以适应内存,你可以执行以下操作:使用内存映射文件将整个文件映射到内存中,然后通过从中间获取数据来执行移动操作文件并将它们移动到开头。然后截断文件。这是从日志文件开头轻松剥离数据而不创建数据副本的唯一方法。

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