After trying a couple of parsers, such as Log Parser 2.2, I ended up writing a small utility that supposedly parses the following information onto an object:(from DirectX Caps Viewer, truncated)DirectX Graphics Adapters   AMD Radeon HD 7800 Series         Driver                          aticfx32.dll         Description                     AMD Radeon HD 7800 Series         DriverVersion                   524305656590         VendorId                        4,098         DeviceId                        26,649         SubSysId                        -501,147,829         Revision                        0         DeviceIdentifier                {D7B71EE2-2B59-11CF-3570-2BC2BEC2C535}         WHQLLevel                       1      Display Modes            640 x 480           D3DFMT_X8R8G8B8                          60            1920 x 1200         D3DFMT_R5G6B5                              60      D3D Device Types         HAL            Caps                  DeviceType                                   1                  MaxPixelShaderValue                          3.40282E+038               Caps                     D3DCAPS_READ_SCANLINE                        Yes               Caps2                     D3DCAPS2_CANCALIBRATEGAMMA                   No                     D3DCAPS2_DYNAMICTEXTURES                     Yes               Caps3                     D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD    Yes               PresentationIntervals                     D3DPRESENT_INTERVAL_ONE                      Yes                     D3DPRESENT_INTERVAL_TWO                      Yes                     D3DPRESENT_INTERVAL_THREE                    Yes                     D3DPRESENT_INTERVAL_FOUR                     Yes                     D3DPRESENT_INTERVAL_IMMEDIATE                Yes               CursorCaps                     D3DCURSORCAPS_COLOR                          Yes                     D3DCURSORCAPS_LOWRES                         No            Adapter Formats               D3DFMT_X8R8G8B8 (Fullscreen)                  Back Buffer Formats                     D3DFMT_A8R8G8B8                        MultiSample Types                              D3DMULTISAMPLE_NONE                              D3DMULTISAMPLE_2_SAMPLESHere's the code.  It basically uses a regular expression to differentiate whether each line is an entry or a category.  Then, using list, it will add that current item to its parent.internal class Program{    private static void Main(string[] args)    {        using (var reader = new StreamReader(File.OpenRead(@..\..\hd7850all.log)))        {            var categories =                new List<Tuple<int, Category>>(new[] {new Tuple<int, Category>(-1, new Category {Name = root})});            while (!reader.EndOfStream)            {                string s = reader.ReadLine();                if (s == null) throw new InvalidOperationException(Input string cannot be null);                //bool isCategory = Regex.IsMatch(s, @^[\w]);                //bool isSubCategory = Regex.IsMatch(s, @^ +(?!.* {2,}));                bool isAnyCategory = Regex.IsMatch(s, @^ *(?!.* {2,}));                bool isEntry = Regex.IsMatch(s, @(?<!^ *) {2,});                int depth = Regex.Match(s, ^ *).Length;                string name = Regex.Replace(s, ^ *, string.Empty);                var category = new Category {Name = name};                var value = new Tuple<int, Category>(depth, category);                if (isAnyCategory)                {                    for (int i = categories.Count - 1; i >= 0; i--)                    {                        Tuple<int, Category> tuple = categories[i];                        if (tuple.Item1 < depth)                        {                            tuple.Item2.Categories.Add(category);                            break;                        }                    }                    categories.Add(value);                }                else if (isEntry)                {                    Tuple<int, Category> tuple = categories.Last();                    tuple.Item2.Entries.Add(new Entry {Name = name});                }            }            Category root = categories[0].Item2;        }    }}public class Category{    public Category()    {        Categories = new List<Category>();        Entries = new List<Entry>();    }    public string Name { get; set; }    public List<Entry> Entries { get; set; }    public List<Category> Categories { get; set; }    public override string ToString()    {        return Name;    }}public class Entry{    public string Name { get; set; }    public override string ToString()    {        return Name;    }}Do you know of a more efficient method or approach to transform such data to an object?
Parsing a text file containing device information
c#;parsing