2

This is the first time I have done any sort of work with flat files. I need this to be a plain txt file NOT XML.

I have written the following opting for a comma delimited format.

    public static void DataTableToFile(string fileLoc, DataTable dt)
    {
        StringBuilder str = new StringBuilder();
        // get the column headers
        foreach (DataColumn c in dt.Columns)
        {
            str.Append(c.ColumnName.ToString() + ",");
        }
        str.Remove(str.Length-1, 1);
        str.AppendLine();
        // write the data here
        foreach (DataRow dr in dt.Rows)
        {
            foreach (var field in dr.ItemArray)
            {
                str.Append(field.ToString() + ",");
            }
            str.Remove(str.Length-1, 1);
            str.AppendLine();
        }
        try
        {
            Write(fileLoc, str.ToString());
        }
        catch (Exception ex)
        {
            //ToDO:Add error logging
        }
    }

My question is: Can i do this better or faster? And str.Remove(str.Length-1, 1); is there to remove the last , which is the only way I could think of. Any suggestions?

Josef Van Zyl
  • 915
  • 3
  • 19
  • 43

2 Answers2

3

Use

public static void DataTableToFile(string fileLoc, DataTable dt)
{
    StringBuilder str = new StringBuilder();

    // get the column headers
    str.Append(String.Join(",", dt.Columns.Cast<DataColumn>()
                                      .Select(col => col.ColumnName)) + "\r\n");

    // write the data here
    dt.Rows.Cast<DataRow>().ToList()
           .ForEach(row => str.Append(string.Join(",", row.ItemArray) + "\r\n"));

    try
    {
        Write(fileLoc, str.ToString());
    }
    catch (Exception ex)
    {
        //ToDO:Add error logging
    }
}
Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208
3

The key point would be: there is no need to construct this in memory with a StringBuilder - you should instead be writing to a file via something like StreamWriter, i.e. via File.CreateText. The API is similar to StringBuilder, but you shouldn't try to remove - instead, don't add - i.e.

bool first = true;
foreach(...blah...) {
    if(first) { first = false; }
    else { writer.Write(','); }
    ... write the data ...
}

As another consideration: CSV is not just a case of adding commas. You need to think about quoted text (for data with , in), and multi-line data. Unless the data is very very simple. You might also want to make the format more explicit than just .ToString(), which is very culture-sensitive. The classic example would be large parts of Europe that use , as the decimal character, thus "CSV" often uses a different separator, to avoid having to quote everything. If the choice is available, personally I'd always use TSV instead of CSV - less problematic (in theory, although you still need to handle data with tabs in).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900