Backend Coder Logo

How To store a List Class to a text file using C#

Published: 19th April 2015

I came up with a very simple way to store a List of objects to a text file where it is easy to view and edit the text data outside of the Application.

The idea is to add methods to the Class to facilitate serialization of the class property values to and from a string. This string consists of Tab-separated strings that represent property values of the Class. And each item from the list is written to a new line in the text file. So it's like CSV format. I used tabs because I may need commas in my property values, but I am unlikely to need Tabs.

More robust text data formats include: XML and JSON. But this method is cool for very simple situations where you want to be able to edit the data in a text editor such as to add more items to the list.

Here is the code for my Class definition:


using System;

namespace Memorizer
{
    class Item
    {
        public string Front { get; set; }
        public string Back { get; set; }
        public int Difficulty { get; set; }
        public int Views { get; set; }

        public Item(string front, string back)
        {
            Front = front;
            Back = back;
            Difficulty = 0;
            Views = 0;
        }

        public Item(string str)
        {
            Front = "";
            Back = "";
            Difficulty = 0;
            Views = 0;

            try
            {
                string[] parts = str.TrimEnd().Split('\t');

                Front = parts[0];
                Back = parts[1];
                if (parts.Length > 2)
                {
                    Difficulty = int.Parse(parts[2]);
                    Views = int.Parse(parts[3]);
                }
            }
            catch (Exception)
            {
            }
        }

        public string Serialize()
        {
            return String.Format("{0}\t{1}\t{2}\t{3}", Front, Back, Difficulty, Views);
        }
    }
}

In the above code I created a Serialize method that produces the string for the text representation of the property values. Also, there is a Constructor method that takes a string as a parameter in order to unserialize the string data and create a new object initialized with the previously saved values.

Now, here is a class to handle the file IO. Note how simple the Save and Load methods are! I used Linq to simplify iterating around the object list/lines of data.


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Memorizer
{
    class Disk
    {
        private static string _dataPath;

        private static string fileName = "data.txt";

        public static string dataPath
        {
            get
            {
                if (null == _dataPath)
                    dataPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Memorizer\\";

                return _dataPath;
            }

            set
            {
                _dataPath = value;
                if (!Directory.Exists(_dataPath))
                    Directory.CreateDirectory(_dataPath);
            }
        }

        public static void Save(List<item> Items)
        {
            File.WriteAllLines(dataPath + fileName, (from i in Items select i.Serialize()));
        }
            

        public static List<item> Load()
        {
            string[] data = File.ReadAllLines(dataPath + fileName);
            return (from i in data select new Item(i)).ToList<item>();
        }
    }
}

I experimented with implementing generic serialization and unserialization methods, but concluded that my custom implementation is the best for simplicity in this scenario. To serialize, it is fine to use the toString method of objects, since you get a number in text format from an Int, and probably True or False strings from bools etc. But when unserializing, the code gets verbose as you have to detect the Type of each property using Reflection and go through a switch statement or other kind of loop to ensure that you cast the value appropriately and without throwing exceptions.