8

I have a list that I want to write to a CSV string.

The examples I have found all seem to be for single item lists, mine has multiple items.

The code I currently have is;

private static string CreateCSVTextFile<T>(List<T> data, string seperator = ",") where T : ExcelReport, new()
{
  var objectType = typeof(T);
  var properties = objectType.GetProperties();
  var currentRow = 0;
  var returnString = "";
  foreach (var row in data)
  {
    var currentColumn = 0;
    var lineString = "";
    foreach (var info in properties)
    {
      lineString = lineString + info.GetValue(row, null) + seperator;
      currentColumn++;
    }
    if (seperator != "")
    {
      lineString = lineString.Substring(0, lineString.Count() - 2);
    }
    returnString = returnString + Environment.NewLine + lineString;
    currentRow++;
  }
  return returnString;
}

But when the list is large this method takes a very long time to run.

The class my list is based on looks like;

internal class ClientMasterFile
{
public String COL1{ get; set; }
public String COL2{ get; set; }
public String COL3{ get; set; }
public String COL4{ get; set; }
public String COL5{ get; set; }
public String COL6{ get; set; }
public String COL7{ get; set; }
public String COL8{ get; set; }
public String COL9{ get; set; }
public String COL10{ get; set; }
public String COL11{ get; set; }
public String COL12{ get; set; }
}

Is there a faster way to do this using an advanced version of String.Join?

Thanks

2
  • 3
    You're using string concatenation. Use StringBuilder. Commented Jul 17, 2013 at 11:12
  • 2
    Create a ToString() method override in your ClientMasterFile and you won't need Reflection because that's what takes so long there. Commented Jul 17, 2013 at 11:14

2 Answers 2

21

Your method can be simplified using StringBuilder and string.Join.

Concatenating strings directly is slow and uses a lot of memory which is fine for small operations.

See: Does StringBuilder use more memory than String concatenation?

private static string CreateCSVTextFile<T>(List<T> data, string seperator = ",")
{
    var properties = typeof(T).GetProperties();
    var result = new StringBuilder();

    foreach (var row in data)
    {
        var values = properties.Select(p => p.GetValue(row, null));
        var line = string.Join(seperator, values);
        result.AppendLine(line);
    }

    return result.ToString();
}

A more complete implementation for CSVs:

private static string CreateCSVTextFile<T>(List<T> data)
{
    var properties = typeof(T).GetProperties();
    var result = new StringBuilder();

    foreach (var row in data)
    {
        var values = properties.Select(p => p.GetValue(row, null))
                               .Select(v => StringToCSVCell(Convert.ToString(v)));
        var line = string.Join(",", values);
        result.AppendLine(line);
    }

    return result.ToString();
}

private static string StringToCSVCell(string str)
{
    bool mustQuote = (str.Contains(",") || str.Contains("\"") || str.Contains("\r") || str.Contains("\n"));
    if (mustQuote)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("\"");
        foreach (char nextChar in str)
        {
            sb.Append(nextChar);
            if (nextChar == '"')
                sb.Append("\"");
        }
        sb.Append("\"");
        return sb.ToString();
    }

    return str;
}

Using: escaping tricky string to CSV format

Sign up to request clarification or add additional context in comments.

1 Comment

You don't need the generic constraints either. I'm glad you found this helpful!
0

we use linqtocsv with some success

https://linqtocsv.codeplex.com

and here is some explanation

http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.