Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write a general Array to CSV file?

Tags:

arrays

c#

csv

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?

like image 990
Andrey Rubshtein Avatar asked Dec 29 '11 10:12

Andrey Rubshtein


2 Answers

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.

like image 138
Oded Avatar answered Oct 21 '22 00:10

Oded


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 + ",");   
    }
}
like image 25
Adam Avatar answered Oct 20 '22 22:10

Adam