17

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,513
  • 29
  • 75
  • 90
user186246
  • 1,857
  • 9
  • 29
  • 45

8 Answers8

41

Try to play around with FileStream.SetLength

FileStream fileStream = new FileStream(...);
fileStream.SetLength(sizeInBytesNotChars);
sll
  • 61,540
  • 22
  • 104
  • 156
  • 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
12

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
  • 53,498
  • 9
  • 91
  • 140
  • 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
6

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
  • 38,903
  • 3
  • 77
  • 117
  • 12
    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,507
  • 3
  • 43
  • 82
Steve
  • 69
  • 1
  • 1
2

By doing this:

if(new FileInfo("<your file path>").Length > 1000000)
{
    File.WriteAllText("<your file path>", "");
}
Arnaud F.
  • 8,252
  • 11
  • 53
  • 102
  • 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
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
  • 17
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
  • 509
  • 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.

KWallace
  • 624
  • 7
  • 15