Link to home
Start Free TrialLog in
Avatar of unreal400
unreal400

asked on

Load CSV into and array c#

I need to load a csv  file with unknown number of rows and columns into a 2d  array.

What is the best way to do this in c#


Avatar of gregoryyoung
gregoryyoung
Flag of Canada image

There are lots of libraries to do this currently available. http://www.google.com/search?hl=en&q=CSV+C%23

I might ask why you need it in array as opposed to another structure (or reading line by line which will work much better for big files as you dont need to hold every item in memory (only the current one)). Either way this one in particular should be pretty easy to work with http://www.codeproject.com/cs/database/CsvReader.asp

Cheers,

Greg
Avatar of unreal400
unreal400

ASKER

The problem  is  we get these files  in and they are not structured in a way that is easy to load.    I have to transpose the entire file to a format that is capaible of loading into a database.  

So if I read line by line  I can't get the data I need.   There is stuff in columns  that should be in rows   etc.   I have no control of the way these files are created but I need to transpose them and load them.   so I just want to put  the whole thing  into and array and write a loop to generate a properly formated file that I can just dts load.

Kelly

If you are working with c# 2005, then this will be a simple solution:

public string[][] ReadCSV(string filename)
{
List<string[]> tempList = new List<string[]>();
string line;
StreamReader reader = new StreamReader(filename);

while ((line = reader.ReadLine()) != null)
{
       tempList.Add(line.Split(","));
}
reader.Close();
return tempList.ToArray();
}

writting from my mind, maybe some bugs....
then just take that code .. read line by line and stuff it in an array or List<List<string>>
there are bugs there jaime .. it doesn't actually support CSV files :) the spec is a bit mroe complex than just splitting on , .. strings can be "" delimited (new lines and commas can appear in strings). Once you support this you also need to handle escaping of quotes in the strings.
I have done this to Excel spreadsheets.  I put them into a DataSet, which is basically an array.  Here is an example:

                        string strStockConnString="Driver={Microsoft Excel Driver (*.xls)};DBQ=" + Server.MapPath("../") + "\\Temp.xls";
                        try
                        {
                              System.Data.Odbc.OdbcDataAdapter objStockDta = new System.Data.Odbc.OdbcDataAdapter("SELECT * FROM [" + txtRange.Text + "]",strStockConnString);
                              DataSet ds = new DataSet();

                              objStockDta.Fill(ds);
                                                                }

txtRange.Text can be a Range defined by you, or a normal Excel Range ie: A1:Z50.  You can define your own range by highlighting the entire area (both rows and columns) and changing it at the top left where you would see the column name (ie "A1").  You need to save the document if you define your own range, but either method is pretty effective.
ASKER CERTIFIED SOLUTION
Avatar of Jaime Olivares
Jaime Olivares
Flag of Peru image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
i'm trying out that solution  Jaime  I'll let you know if it works for what I need.
why are we rewriting code for such a common task here?

using the library I pointed you to ...

    // open the file "data.csv" which is a CSV file with headers
    using (CsvReader csv =
           new CsvReader(new StreamReader(Filename), true))
    {
        int fieldCount = csv.FieldCount;
        string[] headers = csv.GetFieldHeaders();
        List<string[]> Data = new List<string>(); //use array list if you dont have 2.0
        Data.Add(headers); //assuming you want the first row to contain header information
        while (csv.ReadNextRecord())
        {
            string [] row = new string[fieldcount];
            for (int i = 0; i < fieldCount; i++)
                  row[i] = csv[i];
            Data.Add(row);
        }
        return Data.ToArray(); //returns string [][]
    }

not only is this code simpler it also is very well tested and known to completely support the CSV spec.

buy .. don't build (especially when buying is free) :)
jaime   code worked I just had to rewrite a few chunks of it  and  removed your loop  since I don't have quotation marks allowed in these files.

        public string[][] ReadCSV(string filename)
        {
            List<string[]> tempList = new List<string[]>();
            string line;
            StreamReader reader = new StreamReader(filename);

            while ((line = reader.ReadLine()) != null)
            {
                tempList.Add(SplitCSVLine(line));
            }
            reader.Close();
            return tempList.ToArray();
        }

        public string[] SplitCSVLine(string line)
        {
            List<string> result = new List<string>();
            result.AddRange(line.Split(new char[] { ',' }));

            return result.ToArray();
}
why would you bother? the example I gave worked for any valid CSV and was less code ..

btw: why would you do this?

        public string[] SplitCSVLine(string line)
        {
            List<string> result = new List<string>();
            result.AddRange(line.Split(new char[] { ',' }));

            return result.ToArray();
        }

you add your string array to a List<string> just so you can convert them back to a string array?

try ..

        public string[] SplitCSVLine(string line)
        {
            return line.Split(new char[] { ',' });
        }