0

I have a situation that need to make two arrays from each column of csv file. As shown below, the csv file contain two columns each column has a header titled 'period' and 'acceleration'.

Period,Acceleration
0.01,0.6
0.05,0.82
0.1,1.26
0.15,1.403
0.2,1.383

I tried to use following code and then split this into two arrays. However, it did not break the numbers by comma.

string[] allLines = File.ReadAllText(@"C:\ArsScale\Tars.csv").Split(',');
3
  • 1
    I would use a StreamReader and read each line with ReadLine. Then for each line (you need to skip the first line) split it with Split(','). You then have access to an array with two elements, throw the first into one List, and the second into another List. If need be you can convert the lists at the end using ToArray(). Give that a try and come back if you get stuck with a specific part, and include your code so far Commented Jan 13, 2014 at 16:48
  • possible duplicate of C#.NET- Reading CSV file Commented Jan 13, 2014 at 16:55
  • I think what you told me is shown below. I really appreciate your advice. Commented Jan 13, 2014 at 17:05

4 Answers 4

4
static void getTwoArraysFromFile(string filein, ref double[] acc, ref double[] period)
{
    string line;

    List<double> p1 = new List<double>();
    List<double> p2 = new List<double>();

    System.IO.StreamReader file = new System.IO.StreamReader(filein);
    while ((line = file.ReadLine()) != null)
        try {
            String[] parms = line.Trim().Split(',');

            p1.Add(double.Parse(parms[1], CultureInfo.InvariantCulture));       
            p2.Add(double.Parse(parms[0], CultureInfo.InvariantCulture));
        }
        catch { }

    acc = p1.ToArray();
    period = p2.ToArray();
}
Sign up to request clarification or add additional context in comments.

3 Comments

You should read the first line before the loop to skip headers
+1. Good point on using invariant culture - clearly in basic CSV using float numbers with , as decimal separator would be disaster.
@AlexeiLevenkov: If the input file used , for decimal place then the InvariantCulture doesn't help, because the Split(',') will cause a problem first - you would end up with only whole numbers in the results.. both coming from the "Period" data
2
IEnumerable<string[]> allLines = File.ReadAllLines(@"C:\ArsScale\Tars.csv").Select(x => x.Split(','));

This will read all the lines from the text file, then split each line. The datatype will be IEnumerable of string[]. To change this to string[][], simply call .ToArray() after the Select statement.

This method is quick and simple, however it does absolutely no validation on the input. For example, the CSV spec allows for commas to be present inside of values as long as they are escaped. If you need to have validation of any kind, you need to look into a CSV parser, of which there are many.

If you need no validation, you're positive about the input, and don't care about good error handling, you can use the following:

var allLines = File.ReadAllLines(@"C:\ArsScale\Tars.csv").Select(x => x.Split(',').Select(y => double.Parse(y).ToArray())).ToArray();

This will give you double[][] as your output.

2 Comments

+1, I like single LINQ queries just to show how powerful they are
@KonradKokosa ideally I would remove the 2 ToArray() calls and just get back IEnumerable<IEnumerable<double>> however, I think for simplicity sake, ToArray() makes it a little more understandable and avoids any multiple enumeration issues.
1

Use a StreamReader to read your csv line by line. Then split each line and add each value to a list. Finally create two arrays from your lists.

List<Double> periodList = new List<Double>();
List<Double> accelerationList = new List<Double>();

StreamReader file = new System.IO.StreamReader(@"C:\ArsScale\Tars.csv");
string line = file.ReadLine();
while ((line = file.ReadLine()) != null)
{
    string[] data = line.Split(',');
    periodList.Add(Convert.ToDouble(data[0]);
    accelerationList.Add(Convert.ToDouble(data[1]);
}

Double[] periodArray = periodList.ToArray();
Double[] accelerationArray = accelerationList.ToArray();

Comments

0

String.Split is not a robust way of parsing CSV fields, as they may contain commas within the fields etc

In any case you need to use File.ReadAllLines, not File.ReadAllText

File.ReadAllLines gives you a array of strings - 1 for each line.

You could then iterate through the array and copy to 2 other arrays for each item.

Example:

var lines = File.ReadAllLines (@"C:\ArsScale\Tars.csv");
var periods = lines.Skip(1).Select(x => x.Split(",")[0]).ToArray();
var accelerations = lines.Skip(1).Select(x => x.Split(",")[1]).ToArray();

However I'd advise a more robust method.

Have a look at this article: http://www.codeproject.com/Articles/415732/Reading-and-Writing-CSV-Files-in-Csharp

2 Comments

fair enough, added an example implementation
I am reading the linked article. very hellpful. thanks so much!

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.