12

Assume that I have an Array of objects in C#, and I want to write it to a file in CSV format.
Assume that each object has a ToString() method, which is what I want to be printed.

Currently I am using this code:

public static void dumpArray(Array arr, string fileName)
{
    using (System.IO.StreamWriter file = new System.IO.StreamWriter(fileName))
    {
        foreach (Object obj in arr)
        {
             file.Write(obj.ToString()+",");
        }
    }
}

Is there anything built in C# framework, or do you think that there is a better way?

1
  • 1
    I would use your approach as it is much better and faster to achieve just simple csv file. Commented Dec 29, 2011 at 10:27

6 Answers 6

22

Use String.Join:

using (System.IO.StreamWriter file = new System.IO.StreamWriter(fileName))
{
    file.Write(string.Join(",", arr));
}

Though, if you are indeed writing CSV files, you should use a CSV library such as File Helpers, as CSV is not as simple to get right as most people think - see RFC 4180.


Note that the assumption is that you have a string[] as the second parameter - you seem to be passing an instance of the Array class (which is not a string[] as you have written in your question).


Update:

Since you are not passing in a string[], you should be using File Helpers to ensure the objects are written correctly to a CSV.

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

3 Comments

this doesn't compile with his Array arr parameter, only with string[] arr.
I tested it and it casts arr using ToString() method. Not exactly what I want
@Andrey - Why are you using the Array class instead of a string[]?
9

You could change your method to use C# Generics and use descriptive function and variable names. This essentially results in the same behaviour except that boxing is avoided for value types.

public static void SaveArrayAsCSV<T>(T[] arrayToSave, string fileName)
{
    using (StreamWriter file = new StreamWriter(fileName))
    {
        foreach (T item in arrayToSave)
        {
            file.Write(item + ",");
        }
    }
}

Edit: to do the same with jagged Arrays (assuming they only ever contain one level of nesting) you could use this overload (not recommended, see below!):

public static void SaveArrayAsCSV<T>(T[][] jaggedArrayToSave, string fileName)
{
    using (StreamWriter file = new StreamWriter(fileName))
    {
        foreach (T[] array in jaggedArrayToSave)
        {
            foreach (T item in array)
            {
               file.Write(item + ",");
            }
            file.Write(Environment.NewLine);
        }
    }
}

EDIT - Regarding duplication:

The above solution is, of course, sub-optimal in that it only works in a some specific scenarios (where we have exactly one level of nesting). Unfortunately, if refactor our code, we have to stop using generics because our input array might now contain elements of Type Tor of Type T[]. Therefore, we come up with the following code, which is the preferred solution because, although it reintroduces boxing, is more readable, less redundant, and works for a wider range of scenarios:

public static void SaveArrayAsCSV(Array arrayToSave, string fileName)
{
    using (StreamWriter file = new StreamWriter(fileName))
    {
        WriteItemsToFile(arrayToSave, file);
    }
}

private static void WriteItemsToFile(Array items, TextWriter file)
{
    foreach (object item in items)
    {
        if (item is Array)
        {
            WriteItemsToFile(item as Array, file);
            file.Write(Environment.NewLine);
        }
        else file.Write(item + ",");   
    }
}

3 Comments

Can I improve this to support jagged arrays?
Row-wise, all aligned to the left, for example.
This solution doesn't account for a comma existing in one of the fields to be written, or if encapsulating in quotes, taking into account additional quotations in the fields.
2

I believe .csv files can be treated as plain text files .txt. You can easily use:

File.WriteAllText(@"test.csv", string.Join(",", myDataArray));

Comments

1

You are much better of using something like FileHelpers: fast and easy to use: http://www.filehelpers.com/

Comments

1

FileHelper

Not sure about built in CSV libraries as Java supports.

Comments

1

You can also use an extension method:

public static string ToCsv<T>(this IEnumerable<T> ary)
{
  return string.Join(",", ary);
}

and then simply call:

arr.ToCsv();

Being defined for IEnumerable you can also use it for List<>.

2 Comments

if only csv was this simple. this will not work thanks to newlines, and commas, in the csv.
Thanks for pointing this out @gburton, I have updated the answer.

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.