4

我有一个 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它会从最后截断 - 而不是预期的结果。

4

6 回答 6

2

我强烈建议查看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 ILog log;

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

于 2010-02-24T15:34:09.027 回答
0

为什么不检查文件的字节长度是否大于 3MB,如果是,则覆盖它并重新写入。像这样的东西,(我是 ac# 家伙):

System.IO.FileInfo f = new FileInfo(file_name);
if (f.Length > (1024 * 1024 * 3)){
    // 文件超过 3MB
    //
    // 也许备份它?
    // 然后...
    使用 (StreamWriter sw = new StreamWriter(file_name, false))
    {
        // 覆盖内容....
    }
}别的{
    // 以附加模式正常打开
}

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

于 2010-02-24T15:32:37.593 回答
0

一种方法可能是

  1. 逐行读取原始文件(A)
  2. 跳过不需要的行
  3. 将所需的行写入另一个文件 (B)。
  4. 保存文件 B。
  5. 删除文件 A。
  6. 将文件 B 重命名为文件 A。
于 2010-02-24T15:38:38.970 回答
0

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

  If New FileInfo("yourFilePathHere").Length > (2 ^ 21) Then
        File.WriteAllText("yourFilePathHere", _
        File.ReadAllText("yourFilePathHere").Substring(ToInt32(2 ^ 21)))
  End If
于 2010-02-24T15:57:31.957 回答
0

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

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. 缩小文件可能需要一些时间,因此您对日志的写入应该发生在后台线程上。
于 2015-02-10T21:40:47.280 回答
0

我使用的快速简便的方法。此示例保留日志文件的最新 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
于 2016-08-19T15:20:54.437 回答