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

发布于 2024-08-23 07:32:01 字数 417 浏览 3 评论 0原文

我有一个 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 ,它会从末尾开始切断 - 这不是所需的结果。

I have an VB.NET app that writes the status to a log file in text format. Over time, the file is getting large and I wanted to know if there is an efficient way to truncate the beginning of the file.

To make things easier, I am looking to specify a file size (say 2-3 mb) and I am writing the log using a StreamWriter:

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

I thought about using the strm.BaseStream.Length to determine how much of the file to cut off, but by using the .SetLength it would cut from the end - not the desired result.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

你是年少的欢喜 2024-08-30 07:32:01

我强烈建议您查看 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() 中执行此操作:
公共 ILog 日志;

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.");

您不必担心创建流对象、关闭流、处置流等。而且它非常

I would highly suggest looking at log4net to accomplish your logging. It's extremely powerful and flexible and has a built in way of rolling your logs based on a size you can specify. It's not the answer you're looking for here, but it's definitely worth looking into. Here's a sample config for what we do for logging during debug:

<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>

This code in the app.config file will create a log file called ClientTools.log in the application folder, write it in a specific format including the date and time, and roll the log at 3MB.

To use the logger, we do this in Init() of the web page:
public ILog log;

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

And then when you want to log something, do this:

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

You don't have to worry about creating a stream object, closing the stream, disposing the stream, etc. And it's very DRY.

旧人哭 2024-08-30 07:32:01

为什么不检查文件的字节长度是否大于 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
}

希望这有帮助,
此致,
汤姆.

Why not check if the file's length in bytes is greater than 3MB, if it is, overwrite it and write to it afresh. Something like this, (I'm a c# guy):

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
}

Hope this helps,
Best regards,
Tom.

相守太难 2024-08-30 07:32:01

一种方法可以是

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

One approach could be

  1. Read original file(A) line by line
  2. Skip not required lines
  3. Write required lines to another file (B).
  4. save file B.
  5. Delete file A.
  6. Rename file B to file A.
相权↑美人 2024-08-30 07:32:01

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

  If New FileInfo("yourFilePathHere").Length > (2 ^ 21) Then
        File.WriteAllText("yourFilePathHere", _
        File.ReadAllText("yourFilePathHere").Substring(ToInt32(2 ^ 21)))
  End If

You could check the File-Length and truncate it the hard (and dirty) way:

  If New FileInfo("yourFilePathHere").Length > (2 ^ 21) Then
        File.WriteAllText("yourFilePathHere", _
        File.ReadAllText("yourFilePathHere").Substring(ToInt32(2 ^ 21)))
  End If
对岸观火 2024-08-30 07:32:01

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

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. 缩小文件可能需要一些时间,因此您对日志的写入应该在后台线程上进行。

Here are a couple functions that I use for this:

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

There are a couple other things to consider:

  1. You need to run these inside a lock (xxx) so there is NO possibility that another message will attempt to write to the file while the "Shrink" is happening.
  2. Shrinking a file can take a bit of time, so your writes to the log should happen on a background thread.
往事风中埋 2024-08-30 07:32:01

我使用的方法又快又简单。此示例保留日志文件的最新 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

Quick and easy method I use. This example keeps the most recent 60 lines of the log file.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文