14

I am writing actions done by the program in C# into a file by using Trace.Writeln() function. But the file is becoming too large. How to truncate this file when it grows to 1MB?

TextWriterTraceListener traceListener = new TextWriterTraceListener(File.AppendText("audit.txt"));
Trace.Listeners.Add(traceListener);
Trace.AutoFlush = true;

What should be added to the above block

Dour High Arch
  • 21,081
  • 29
  • 74
  • 89
user186246
  • 1,767
  • 9
  • 27
  • 45

8 Answers8

39

Try to play around with FileStream.SetLength

FileStream fileStream = new FileStream(...);
fileStream.SetLength(sizeInBytesNotChars);
sll
  • 59,352
  • 21
  • 103
  • 153
  • 1
    +1 If OP is using `FileStream` this is the simplest solution, using `SetLength(0)`. – Steve Townsend Jun 30 '11 at 16:49
  • After terminating the process, if I recreate a new process then the above code will append the text to the existing file? – user186246 Jun 30 '11 at 16:50
  • If you do `SetLength(0)` on an active `FileStream`, that will truncate the underlying file. – Steve Townsend Jun 30 '11 at 16:53
  • We note that FileStream.SetLength with a non-zero length is a very bad idea for a log file; however I found this question with a more reasonable case where this is the correct solution. – Joshua Jun 03 '15 at 16:23
11

Close the file and then reopen it using FileMode.Truncate.

Some log implementations archive the old file under an old name before reopening it, to preserve a larger set of data without any file getting too big.

Steve Townsend
  • 52,418
  • 9
  • 90
  • 139
  • 1
    This will truncate the file down to 0 bytes, i.e. you throw away the whole thing. That might be what the OP wants to do...or they might want to keep some of it, in which case don't do this. – Rory Jun 17 '12 at 15:12
8

As opposed to trying to do this yourself, I'd really recommend using something like log4net; it has a lot of this sort of useful functionality built in.

Paul Sonier
  • 37,815
  • 3
  • 74
  • 116
  • 10
    Since you're not actually answering the question, this should be a comment. – Gabe Jun 30 '11 at 16:26
  • 4
    @Gabe: I don't think it's an inappropriate answer to a question to answer that the OP's stated method shows some inefficiencies, and to suggest an alternate method. – Paul Sonier Jun 30 '11 at 16:29
  • 4
    Good answers show code or link to the specific function to use. If you want this to be a good answer, show how to use log4net to do what the OP is asking. – Gabe Jun 30 '11 at 16:39
6

When the file is over 500000 bytes, it will cut the beginning 250000 bytes off from the file so the remaining file is 250000 bytes long.

FileStream fs = new FileStream(strFileName, FileMode.OpenOrCreate);
        if (fs.Length > 500000)
        {
            // Set the length to 250Kb
            Byte[] bytes = new byte[fs.Length];
            fs.Read(bytes, 0, (int)fs.Length);
            fs.Close();
            FileStream fs2 = new FileStream(strFileName, FileMode.Create);
            fs2.Write(bytes, (int)bytes.Length - 250000, 250000);
            fs2.Flush();
        } // end if (fs.Length > 500000) 
Noctis
  • 11,175
  • 3
  • 40
  • 79
Steve
  • 69
  • 1
  • 1
1

If you have no desire to keep the contents, or move them into a subsidiary file that tracks the update for the cycle (whether by day or some other cycle length), I would recommend just rewriting the file using this simple method:

    private void Truncate(readFile)     // to clear contents of file and note last time it was cleared
    {
        string readFile = readPath + ".txt";
        string str = string.Format("{0} : Truncated Contents", DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"));
        using (StreamWriter truncate = new StreamWriter(readFile))
        {
            truncate.WriteLine(str); // truncates and leaves the message with DateTime stamp
        }
    }

If, on the other hand, you want to save the contents to a file for the date they were truncated, you can use the following method in conjunction with the above:

    private void Truncate(readPath)     // to clear contents of file, copy, and note last time it was cleared and copied
    {
        if (!File.Exists(readPath))    // create the new file for storing old entries
        {
            string readFile = readPath + ".txt";
            string writeFile = readPath + DateTime.Now.ToString("_dd-MM-yyyy_hh-mm") + ".txt"; // you can add all the way down to milliseconds if your system runs fast enough
            using (FileStream fs = new FileStream(writeFile, FileMode.OpenOrCreate, FileAccess.Write))
            {
                using (StreamWriter write = new StreamWriter(fs))
                using (StreamReader file = new StreamReader(readFile))
                {
                    write.WriteLine(string.Format(textA, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
                    string line;
                    var sb = new StringBuilder();
                    while ((line = file.ReadLine()) != null)
                    {
                        line = line.Replace("\0", ""); // removes nonsense bits from stream
                        sb.AppendLine(line);
                    }
                    write.WriteLine(sb.ToString());
                    string textB = "{0} : Copied Source";
                    write.WriteLine(string.Format(textB, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
                }
            }
            string str = string.Format("{0} : Truncated Contents", DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"));
            using (StreamWriter truncate = new StreamWriter(readFile))
            {
                truncate.WriteLine(str); // truncates and leaves the message with DateTime stamp
            }
        }
    }

Either way, you can utilize the method of your choice with the following block:

if(new FileInfo("audit.txt").Length >= 0xfffff) // hex for 1MB
{
    Truncate("audit");
}

I hope this helps future readers.

Thanks,

CSS
  • 412
  • 5
  • 16
1

By doing this:

if(new FileInfo("<your file path>").Length > 1000000)
{
    File.WriteAllText("<your file path>", "");
}
Arnaud F.
  • 7,961
  • 11
  • 51
  • 100
  • I suggest taking a look at the value `1000000`... remember, `1 kbyte = 1024 bytes`, and the same applies for `mb` – Oscar Mederos Jun 30 '11 at 16:28
  • Personally I would not check the file length this way, it's going to require a lot of `new FileInfo` calls (one per write). Most likely the class the OP is using to write to the file has some way to track the size, if it's a `FileStream` for example use the `Position` property. – Steve Townsend Jun 30 '11 at 16:33
  • @Oscar: I know, it's just to give the main idea, it needs to be adapted. – Arnaud F. Jun 30 '11 at 16:36
  • this wouldn't be able to do a rolling log. – John Lord Jan 23 '22 at 21:42
0

Perhaps this would be simple solution:

// Test the file is more or equal to a 1MB ((1 * 1024) * 1024)
// There are 1024B in 1KB, 1024KB in 1MB
if (new FileInfo(file).length >= ((1 * 1024) * 1024))
{
    // This will open your file. Once opened, it will write all data to 0
    using (FileStream fileStream = new FileStream(file, FileMode.Truncate, FileAccess.Write))
    {
        // Write to your file.
    }
}
Jason Cidras
  • 491
  • 5
  • 11
0

Late answer, but you might try:

StreamWriter sw = new StreamWriter(YourFileName, false);
sw.Write("");
sw.Flush();
sw.Close();

Sending false as the second param of StreamWriter() tells it NOT to append, resulting in it overwriting the file. In this case with an empty string, effectively truncating it.

Kirby L. Wallace
  • 552
  • 4
  • 13