【问题标题】:Keeping log files under a certain size将日志文件保持在一定大小
【发布时间】:2011-01-19 21:34:39
【问题描述】:

我有一个在信息亭 (C#/WPF) 中的独立平板电脑上运行的应用程序。它对文本文件执行一些典型的日志记录操作。随着日志的增长,PC 有一些有限的磁盘空间来存储这些日志。

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

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

【问题讨论】:

    标签: c# file logging filesize file-manipulation


    【解决方案1】:

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

    诸如 log4net 之类的日志框架内置了此功能。

    【讨论】:

      【解决方案2】:

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 可行选项的精彩总结。
        【解决方案4】:

        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/

        【讨论】:

          【解决方案5】:

          我不会将它用于超过 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);
                  }
              }
          }
          

          【讨论】:

            【解决方案6】:

            我也想要一个简单的解决方案,但我不想添加另一个依赖项,所以我做了一个简单的方法。除了将旧文件压缩为 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);
                }
            }
            

            我将此作为我的应用程序的初始化/重新初始化部分的一部分,因此它每天运行几次。

            ErrorLogging.ManageLogs("Application.log");
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-02-16
              • 2016-12-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多