Sunday, June 1, 2003

These Are a Few of My Favorite Things

I was writing some code Friday, and I realized I was working with three
of my favorite namespaces all at once:
System.IO, System.Xml, and System.Diagnositcs.
Most people will have used all of these namespaces at least once, but there are a
bunch of hidden gems that not everyone will have seen.

The task I was trying to pull off was to dump an XML document for debugging
purposes. I wanted to send it both to the console and to a logfile, to give me a real-time
idea of what was going on as well as a permanent record I could go back and analyze

The ability to write a piece of information to more than one place
for diagnostic purposes just cries out for
So I started my program off with the following lines of code:

using System;

using System.IO;

using System.Diagnostics;

public class App


  public static void Main()



      new TextWriteTraceListener(Console.Output));

    string logfile =

+ ".txt";


      new TextWriteTraceListener(logfile);

which sets it up so that any time I call Trace.WriteLine,
a piece of text is written both to the command console and to a logfile whose name
is derived from the current date and time. The overload of ToString that
lets you specify the exact format for the date and time is pretty cool, I think.

Later, when I wanted to actually dump the XML, I did this:

StringWriter sw = new StringWriter();

XmlTextWriter wtr = new XmlTextWriter(sw);

wtr.Formatting = Formatting.Indented;




where xml is the XmlDocument that
I wanted to dump out.

There are a number of cool things in these few lines of code:

·        The StringWriter class
give you a stream that  you can use anywhere you’d use a normal TextWriter (e.g.
the constructor of XmlTextWriter),
but it writes to an internally maintained StringBuilder instead.

·        The Formatting property
of XmlTextWriter to get that nice “every
nested element gets indented one level” look. Makes for much more readable output.

·        Of
course, the call to Trace.WriteLine to
actually spew this same XML to more than once place.

A few caveats:

·        You
need to define the symbol TRACE in your build (Project Properties->Configuration
Properties->Build->Conditional Compilation Constants – just type in TRACE)
or Trace.WriteLine will not even make
it into the compiled program.

·        I
found that I needed to go through and flush each trace listener independently, or
my log file would get truncated. That was easy, though: just a foreach loop over the Trace.Listeners collection,
calling Flush and Close on
each TraceListenener.  


  1. Nice article. FYI, the first code snippet shows you adding Console.Output to the Trace.Listener collection twice. Also, I think you meant StringBuilder when you said StringBuffer (perhaps you've been doing some Java programming lately).

  2. D'oh. Right on both counts. I'll fix it.