views:

248

answers:

4

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.

A: 

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.

tommieb75
+2  A: 

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.

Chris Conway
I didn't really want to go this route, but I think this is what is going to have to be done. The logging was originally designed to be very simple but, to do it properly, this would work. Thanks.
hacker
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.
Mani
A: 

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
Bobby
This could work, but I think that if 2 log entries came really close to each other, it would possibly cause an issue with writing the file or truncating the other log entry.
hacker