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(',');
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
user3170073
  • 193
  • 1
  • 9
  • 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 – musefan Jan 13 '14 at 16:48
  • possible duplicate of [C#.NET- Reading CSV file](http://stackoverflow.com/questions/5282999/c-net-reading-csv-file) – Alexei Levenkov Jan 13 '14 at 16:55
  • I think what you told me is shown below. I really appreciate your advice. – user3170073 Jan 13 '14 at 17:05

4 Answers4

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();
}
Exceptyon
  • 1,584
  • 16
  • 23
  • 1
    You should read the first line before the loop to skip headers – Plue Jan 13 '14 at 16:59
  • 1
    +1. Good point on using invariant culture - clearly in basic CSV using `float` numbers with `,` as decimal separator would be disaster. – Alexei Levenkov Jan 13 '14 at 17:00
  • 1
    @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 – musefan Jan 14 '14 at 09:12
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.

Pete Garafano
  • 4,863
  • 1
  • 23
  • 40
  • +1, I like single LINQ queries just to show how powerful they are – Konrad Kokosa Jan 13 '14 at 17:00
  • @KonradKokosa ideally I would remove the 2 `ToArray()` calls and just get back `IEnumerable>` however, I think for simplicity sake, `ToArray()` makes it a little more understandable and avoids any multiple enumeration issues. – Pete Garafano Jan 13 '14 at 17:08
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();
Plue
  • 1,739
  • 1
  • 18
  • 22
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

James S
  • 3,558
  • 16
  • 25