代码之家  ›  专栏  ›  技术社区  ›  hacker

在.NET中截断日志文件的开头

  •  3
  • hacker  · 技术社区  · 15 年前

    我有一个vb.net应用程序,它将状态以文本格式写入日志文件。随着时间的推移,文件越来越大,我想知道是否有一种有效的方法来截断文件的开头。

    为了使事情更简单,我要指定一个文件大小(例如2-3 MB),并使用streamwriter编写日志:

    Using strm As New IO.StreamWriter(filelocation.log, True)
        strm.WriteLine("msg to write")
        strm.Close()
    End Using
    

    我想用 strm.BaseStream.Length 确定要剪切多少文件,但使用 .SetLength 它会从末端切下来——而不是期望的结果。

    6 回复  |  直到 8 年前
        1
  •  2
  •   Chris Conway    15 年前

    我强烈建议你看看 log4net 完成日志记录。它非常强大和灵活,有一种内置的方式,可以根据您指定的大小滚动日志。这不是你要找的答案,但绝对值得一看。以下是调试期间日志记录的配置示例:

    <log4net>
        <appender name="GeneralLog" type="log4net.Appender.RollingFileAppender">
            <file value="ClientTools.log"/>
            <appendToFile value="true"/>
            <maximumFileSize value="3000KB"/>
            <rollingStyle value="Size"/>
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%d{HH:mm:ss} [%t] %-5p %c - %m%n"/>
            </layout>
        </appender>
        <root>
            <level value="DEBUG"/>
            <appender-ref ref="GeneralLog"/>
        </root>
        <logger name="NHibernate" additivity="false">
            <level value="DEBUG"/>
            <appender-ref ref="GeneralLog"/>
        </logger>
    </log4net>
    

    app.config文件中的这段代码将在应用程序文件夹中创建一个名为clienttools.log的日志文件,以包括日期和时间在内的特定格式写入,并以3MB滚动日志。

    要使用记录器,我们在网页的init()中执行此操作: 公共劳工日志;

    public void InitiateLogging()
    {
        log4net.Config.XmlConfigurator.Configure();
        log = LogManager.GetLogger("MyApplication");
    }
    

    然后当你想记录一些东西时,请执行以下操作:

    log.Info("No resources available.");
    // or
    log.Fatal(exception.Message);
    // or
    log.Warn("Something bad may happen here.");
    

    您不必担心创建流对象、关闭流、处理流等,而且 DRY .

        2
  •  0
  •   t0mm13b    15 年前

    为什么不检查文件的字节长度是否大于3MB,如果大于3MB,覆盖它并重新写入。像这样,(我是一个C人):

    System.IO.FileInfo f = new FileInfo(file_name);
    if (f.Length > (1024 * 1024 * 3)){ 
        // File is over 3MB
        //
        // Perhaps back it up?
        // Then...
        using (StreamWriter sw = new StreamWriter(file_name, false))
        {
            // Overwrite the contents....
        }
    }else{
        // Open as normal for append mode
    }
    

    希望这有帮助, 最好的问候, 汤姆。

        3
  •  0
  •   Mani    15 年前

    一种方法是

    1. 逐行读取原始文件(A)
    2. 跳过不需要的行
    3. 将所需行写入另一个文件(b)。
    4. 保存文件B。
    5. 删除文件A。
    6. 将文件B重命名为文件A。
        4
  •  0
  •   Bobby    15 年前

    您可以检查文件长度并以硬(脏)方式截断:

      If New FileInfo("yourFilePathHere").Length > (2 ^ 21) Then
            File.WriteAllText("yourFilePathHere", _
            File.ReadAllText("yourFilePathHere").Substring(ToInt32(2 ^ 21)))
      End If
    
        5
  •  0
  •   Doug Clutter    10 年前

    以下是我用于此的几个函数:

    private void ShrinkLogFile()
    {
        var file = new FileInfo(Filename);
        if (file.Exists && file.Length > MaxFileSize)
        {
            MoveLinesToBeginningStartingAt(file.Length - (MaxFileSize / 2));
        }
    }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
    private void MoveLinesToBeginningStartingAt(long offsetToKeep)
    {
        // Open the file twice.  We'll read from the end and write to the beginning.
        using (var fileReader = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        using (var fileWriter = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
        {
            // Find the end of the first line so we start at the beginning of a new line.
            fileReader.Position = offsetToKeep;
            using (var reader = new StreamReader(fileReader, Encoding.UTF8, true, 512, true))   // Note that we leave fileReader open...
            {
                offsetToKeep += reader.ReadLine().Length;       // Advance offset past the (probably) partial first line
                offsetToKeep += Environment.NewLine.Length;     // Advance past the newline
            }
    
            // Go to new position and copy the rest of the file to the beginning of the same file.
            fileReader.Position = offsetToKeep;
            fileReader.CopyTo(fileWriter);
    
            // Truncate the file
            var fileInfo = new FileInfo(Filename);
            fileWriter.SetLength(fileInfo.Length - offsetToKeep);
        }
    }
    

    还有其他一些事情需要考虑:

    1. 您需要在锁(xxx)内运行这些代码,这样就不会有其他消息在“收缩”发生时试图写入文件。
    2. 收缩文件可能需要一些时间,因此您应该在后台线程上写入日志。
        6
  •  0
  •   philzy127    8 年前

    我使用的方法又快又简单。此示例保留日志文件的最近60行。

    dim LogPath as string = "YourLogPath"    
    Dim lineCount = File.ReadAllLines(LogPath).Length
    
            If lineCount > 60 Then ' because I want my log to be 60 lines long
                Dim delLineCount As Integer = lineCount - 60
                Dim lines As List(Of String) = New List(Of String)(File.ReadAllLines(LogPath))
                lines.RemoveRange(0, delLineCount)
                File.WriteAllLines(LogPath, lines.ToArray())
            End If