-3

I've created an iPhone app that has a dictionary array of locations (lat,long,point). I created the array by manually entering each value.

myLocationArray = @[
                 @{
                   kStation : @"1",
                   kLatitude : @( 41.656467),
                   kLongitude : @(-81.277963)
                   },
                 @{
                   kStation : @"2",
                   kLatitude : @(41.657118),
                   kLongitude : @(-81.276545)
                   },
                 @{
                   kStation : @"3",
                   kLatitude : @(41.658493),
                   kLongitude : @(-81.273542)
                   },
                  ...

This is good and works but now I want to create this array programmatically by getting the data from a .CSV file. I have a .CSV file (TestCSV.csv) that looks like this.

41.656467,-81.277963,27200
41.657118,-81.276545,27650
41.658493,-81.273542,28631.5
41.660728,-81.268547,30195
41.661830,-81.266065,30991
41.662828,-81.263819,31700
41.663677,-81.261962,32300
41.664578,-81.259909,32950
41.666210,-81.256312,34100
41.666921,-81.254708,34605
41.668043,-81.252191,35400
41.669044,-81.250043,36099
41.670120,-81.247495,36900
41.670778,-81.245957,37380
41.671459,-81.244292,37905
41.672028,-81.242832,38349
41.672487,-81.241702,38700
41.673106,-81.240175,39175
41.674364,-81.237007,40150
41.675170,-81.235038,40762.5
41.675716,-81.233698,41182
41.676143,-81.232614,41516

Specifically, I'd like to create myLocationArray (with formatting as shown) by reading straight from the TestCSV.csv. I'm not familiar with the code to achieve this and would really appreciate some direction.

Also, would it be any different or easier if the data was provided via text file instead of csv?

JBeesky
  • 309
  • 2
  • 14
  • Have you done any searching on parsing CSV files? There are plenty of existing question here or found on Google that will help you parse a CSV file with Objective-C. – rmaddy May 11 '13 at 16:21
  • possible duplicate of [Using NScanner to parse CSV File to Dictionary Array](http://stackoverflow.com/questions/16503084/using-nscanner-to-parse-csv-file-to-dictionary-array) – matt May 12 '13 at 15:02
  • 1
    Direct duplicate of your own question - please do not do that – matt May 12 '13 at 15:03

3 Answers3

5

Try

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Locations" ofType:@"csv"];
NSString *csvString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

NSArray *locations = [csvString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

NSMutableArray *locationsArray = [NSMutableArray array];
for (NSString * location in locations)
{

    NSArray *components = [location componentsSeparatedByString:@","];

    double latitude   = [components[0] doubleValue];
    double longitude  = [components[1] doubleValue];
    NSString *station =  components[2];

    NSDictionary *dict = @{@"kLatitude": @(latitude),
                           @"kLongitude": @(longitude),
                           @"kStation": station};

    [locationsArray addObject:dict];

}

CSV File

Answer inspired from

Community
  • 1
  • 1
Anupdas
  • 10,211
  • 2
  • 35
  • 60
  • I was not able to create an array from this. In *filepath should pathForResource: be @"TestCSV" since that is the name of my csv file that contains my data? Aside from that, I get the error *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]' – JBeesky May 11 '13 at 23:02
  • Using the debugger and breaks, I think the problem lies in this call, [components enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [dict setObject:obj forKey:keys[idx]]; }];. I'm not sure how this works but perhaps you can make sense of why it's causing the error I posted in the previous comment. – JBeesky May 11 '13 at 23:53
  • @JBeesky Did you use the exact code that I provided? Everything is working fine for me. First check with the CSV that I used. Check what is different in both. In enumeration I have used the idx to find the key, if the idx comes more than 2, it would break. It would more easier if you provide the CSV you used. – Anupdas May 12 '13 at 03:59
  • I updated my question to show the actual csv file data I'm using in my project. I don't think there would be an index 3 though. – JBeesky May 12 '13 at 13:59
1

csv file IS a plain-text file. To achive what you want you can use NSScanner and NSString componentsSeparatedByString: Everything else is really simple.

creker
  • 9,400
  • 1
  • 30
  • 47
  • 1
    Using `componentsSeparatedByString:` to parse a CSV file only works in very specific cases. It won't work if values are quoted and values contain field delimiters. It won't work when values contain newlines. Admittedly, it may work in this specific case since this CSV file appears not to have any text but it is not a valid, general purpose solution for parsing CSV files. – rmaddy May 11 '13 at 16:24
  • 1
    No one asked for general purpose solution. Topic starter gave file example he want to parse. It can be parsed with method I mentioned. I'm not a fan of general purpose solutions when they are clearly unnecessary. – creker May 11 '13 at 16:33
  • I was simply pointing out the potential downsides to your answer for the benefit of people who may find your answer in the future. Remember, people will search and find such answers long into future and such users may have a more general need. I stated in my comment that your answer is fine for this use. – rmaddy May 11 '13 at 16:51
  • Thanks for the response guys. I'm looking into NSSCanner. I'll report back after I do some research. – JBeesky May 11 '13 at 23:54
  • Guys, I posted a new question at the following link in response to your suggestion to use NSScanner. I'd like keep this question open as well for the possibility that Anupdas's method may work. Please review and comment to http://stackoverflow.com/questions/16503084/using-nscanner-to-parse-csv-file-to-dictionary-array. I appreciate the help. – JBeesky May 12 '13 at 00:48
  • I closed the questioned I linked to above since I've found an answer here. – JBeesky May 14 '13 at 01:04
1

Answer provided by Anupdas. Cheers!

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Locations" ofType:@"csv"];
NSString *csvString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

NSArray *locations = [csvString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

NSMutableArray *locationsArray = [NSMutableArray array];
for (NSString * location in locations)
{

NSArray *components = [location componentsSeparatedByString:@","];

double latitude   = [components[0] doubleValue];
double longitude  = [components[1] doubleValue];
NSString *station =  components[2];

NSDictionary *dict = @{@"kLatitude": @(latitude),
                       @"kLongitude": @(longitude),
                       @"kStation": station};

[locationsArray addObject:dict];

}

JBeesky
  • 309
  • 2
  • 14