Load data from csv file (iphone SDk) - iphone

Does anyone know how to load data from csv file?
For the code example,
CPTestAppScatterPlotController.m
that I downloaded from core-plot Google website, a line graph can be plotted based on randomly
generated initial data x, y.
// Add some initial data
SMutableArray *contentArray = [NSMutableArray arrayWithCapacity:100];
NSUInteger i;
for ( i = 0; i < 60; i++ ) {
id x = [NSNumber numberWithFloat:1+i*0.05];
id y = [NSNumber numberWithFloat:1.2*rand()/(float)RAND_MAX + 1.2];
[contentArray addObject:[NSMutableDictionary
dictionaryWithObjectsAndKeys:x, #"x", y, #"y", nil]];
}
self.dataForPlot = contentArray;
Then i modified the code,
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"ECG_Data" ofType:#"csv"];
NSString *myText = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil ];
NSScanner *scanner = [NSScanner scannerWithString:myText];
[scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:#"\n, "]];
NSMutableArray *newPoints = [NSMutableArray array];
float time, data;
while ( [scanner scanFloat:&time] && [scanner scanFloat:&data] ) {
[newPoints addObject:
[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:time], #"time",
[NSNumber numberWithFloat:data], #"data",
nil]];
}
self.dataForPlot = newPoints;
It seems that my code could not read the data from csv file.
(there are two cols of the data in ECG_Data.csv, one for time and one for data)
Can anyone give me some suggestion???
Thanks!!!!

http://cocoawithlove.com/2009/11/writing-parser-using-nsscanner-csv.html
Here is a good place to start for creating a CSV parser. It's complete with sample code and user comments.

Related

Search in .csv file

I have an .csv file with round about 10.000 Lines.
Now I have a textfield in which the User typing a value than he Click on a Button.
Now this value should be searching in the .csv and then in this Linie all values should be Displayed in a Label
E.g.
.csv:
PLZ, Name, Code 47158, Neuss, DE005116 46356, Moers, DE006151
ViewControler:
Textfield search: 47158
Label1: Neuss
Label2: DE005116
Thanks for helping
1 google search would have made you happy ;)
http://www.macresearch.org/cocoa-scientists-part-xxvi-parsing-csv-data
EDIT To answer your question below.
while ([scanner scanFloat:&myVariable] && [scanner scanFloat:&myVariable2] && [scanner scanFloat:&myVariable3]) {
[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:myVariable], #"theKeyInTheCSV",
[NSNumber numberWithFloat:myVariable2], #"theKeyInTheCSV2",
[NSNumber numberWithFloat:myVariable3], #"theKeyInTheCSV3",
nil]];
}
her is my code:
-(IBAction)Zollamtsname:(id)sender{
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Zollämter Access" ofType:#"csv"];
NSString *myText = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil ];
NSLog(#"%#", [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]);
if ( nil == mytext ) return NO;
NSScanner *scanner = [NSScanner scannerWithString:myText];
[scanner setCharactersToBeSkipped:
[NSCharacterSet characterSetWithCharactersInString:#"\n, "]];
NSMutableArray *newPoints = [NSMutableArray array];
float test1, test2;
while ( [scanner scanFloat:&test1] && [scanner scanFloat:&test2] ) {
[newPoints addObject:
[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:test1], #"test1",
[NSNumber numberWithFloat:test2], #"test2",
nil]];
}
[self setPoints:newPoints];
return YES;
}
//[self.Zollamzsnummer setText:#"test"];
}
i get 4 errors and I don't know how so solve them :( 1."return NO" = the void method should not return a value
2. "return YES" = the void method should not return a value
3. [self setPoints:newPoints]; = Not visible #interface for'ViewController_suche'declares the selector setPoints
ANd who I say that the serach value is in the textfield?

Highest 4 Numbers From Array #1 To Store In Another Array

So I have three different arrays involved here...
I'm looping through golferThreeIcons (NSMutableArray), and I'm trying to take the highest 4 results (golferThreeIcons contains #'s as strings) and store them into the topFourIconsNum (NSMutableArray) and then I plan to store the id of that highest number in the array topFourIconsId (NSMutableArray).
One tricky thing is that golferThreeIcons start out at 99, but I want that to act like zero. So the number 99 should not get added to either of the arrays...
Example:
golferThreeIcons {2,1,5,3,9}
And after the loop went through I want it to show something like this...
topFourIconsId {0,2,3,4} --- 0 corresponds to 2 in golferThreeIcons --- 2 corresponds to 5 in golfer three icons
topFourIconsNum {2,5,3,9} ----(in any order as long as it corresponds to the top four icons id)
NSMutableArray *topFourIconsId = [NSMutableArray arrayWithObjects: #"0", #"0", #"0", #"0", #"0" ,nil];
NSMutableArray *topFourIconsNum = [NSMutableArray arrayWithObjects: #"0", #"0", #"0", #"0", #"0" ,nil];
int *ids = 0;
for (NSString *s in golferThreeIconCounter) {
if(s != #"0") {
int sint = [s intValue];
int *idn = 0;
for(NSString *n in topFourIconsNum) {
int nint= [n intValue];
if(sint == 99 && nint == 0) {
NSString *idstring = [NSString stringWithFormat:#"%d", ids];
NSString *sintstring = [NSString stringWithFormat:#"%d", sint];
[topFourIconsId replaceObjectAtIndex:idn withObject:idstring];
[topFourIconsNum replaceObjectAtIndex:idn withObject:sintstring];
NSLog(#"IN %#",sintstring);
break;
}
else {
if (sint > nint) {
NSString *idstring = [NSString stringWithFormat:#"%d", ids];
NSString *sintstring = [NSString stringWithFormat:#"%d", sint];
[topFourIconsId replaceObjectAtIndex:idn withObject:idstring];
[topFourIconsNum replaceObjectAtIndex:idn withObject:sintstring];
NSLog(#"IN %#",sintstring);
break;
}
}
idn++;
}
}
ids++;
}
Just a crazy idea
Put your golferThreeIcons in a NSDictionary with the array index as the key and the array value as the value and then sort the keys on their value:
NSDictionary *dict = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"2", #"1", #"5", #"3", #"9", nil] forKeys:[NSArray arrayWithObjects:#"0", #"1", #"2", #"3", #"4", nil]];
NSArray *sortedKeys = [dict keysSortedByValueUsingSelector:#selector(caseInsensitiveCompare:)];
NSLog([sortedKeys description]);

Problem with CGImageDestination and file naming

I am capturing images from the camera, using AVCapture as I have need of speed and the standard kit stuff is way too slow.
I have problem whereby the file that is being output (an animated GIF) is having it's file name mangles by the CGImageDestination functions...
When I output the NSURL (cast to a CFURLRef) to the log I get the path/filename I intended:
2011-09-04 20:40:25.914 Mover[3558:707] Path as string:.../Documents/91B2C5E8-F925-47F3-B539-15185F640828-3558-000003327A227485.gif
However, once the file is created and saved it actually lists the filename as this:
2011-09-04 20:40:25.960 Mover[3558:707] file: .91B2C5E8-F925-47F3-B539-15185F640828-3558-000003327A227485.gif-TtNT
See the difference? the period at the start and the 4 character suffix?
Whats really wierd is that it doesn't always do it, about 40% of the time it works OK. However it's preventing the code working further down the line where I'm listing them with previews in a table view.
Does anyone know why and how to stop it doing this?
Here's the code:
- (void)exportAnimatedGif{
NSString *guidPath = [[NSProcessInfo processInfo] globallyUniqueString];
NSString *tmpPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:guidPath];
NSString *path = [tmpPath stringByAppendingPathExtension:#"gif"];
NSLog(#"Path as string:%#", path);
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], kUTTypeGIF, [captureArray count], NULL);
NSDictionary *frameProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:testDisplay3.displayValue] forKey:(NSString *)kCGImagePropertyGIFDelayTime]
forKey:(NSString *)kCGImagePropertyGIFDictionary];
NSDictionary *gifProperties = [NSDictionary dictionaryWithObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:2], (NSString *)kCGImagePropertyGIFLoopCount,
[NSNumber numberWithFloat:testDisplay3.displayValue], (NSString*)kCGImagePropertyGIFDelayTime,
[NSNumber numberWithFloat:testDisplay3.displayValue], (NSString*)kCGImagePropertyGIFUnclampedDelayTime,
nil]
forKey:(NSString *)kCGImagePropertyGIFDictionary];
for (int ii = 0; ii < [captureArray count]; ii++)
{
UIImage *tmpImg = [[UIImage alloc] init];
tmpImg = [captureArray objectAtIndex:ii];
CGImageDestinationAddImage(destination, tmpImg.CGImage, (CFDictionaryRef)frameProperties);
}
CGImageDestinationSetProperties(destination, (CFDictionaryRef)gifProperties);
CGImageDestinationFinalize(destination);
CFRelease(destination);
//TEST OUTPUT GENERATED FILES
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] error:nil];
for (int xx = 0; xx < [contents count]; xx++)
{
NSLog(#"file: %#", [contents objectAtIndex:xx]);
}
//END TEST CODE
[captureArray removeAllObjects];
}
AFAIK this is a temporary file that CGImageDestinationFinalize makes, the reason you see them is that CGImageDestinationFinalize failed. I think that if you check the file sizes you'll see that the ones with mangled names have a file size of 0.
I started check for succes after I got these files :)
bool success = CGImageDestinationFinalize(destination);
CFRelease(destination);
if (success) {
NSLog(#"animated GIF file created at %#", path);
} else {
NSLog(#"failed to create gif at %#", path);
}

Build string with variable number of keys and formats

I have an NSDictionary object that contains my data. I am passing in an array of key names and a display format for a string representation of my data.
[self displayMyDataWithTheseKeys:myKeyArray inThisFormat:myFormat];
where, for example,
myKeyArray = [NSArray arrayWithObjects: #"Key1", #"Key2", nil];
myFormat = [NSString stringWithString: #"%# to the %# degree"];
However, myFormat may change and the number of keys in the array may vary as well.
If the number of elements in the array was always 2, this would be trivial. However, how can I handle a variable number of elements?
There isn't really a built-in method for this, but it's relatively easy to parse format strings with NSScanner. Here's a simple example, it only handles %# format specifiers, but as all elements in an NSArray are objects and not primitive types anyway, it shouldn't matter:
NSArray *myKeyArray = [NSArray arrayWithObjects: #"Key1", #"Key2", nil];
NSString *myFormat = [NSString stringWithString: #"%# to the %# degree"];
NSMutableString *result = [NSMutableString string];
NSScanner *scanner = [NSScanner scannerWithString:myFormat];
[scanner setCharactersToBeSkipped:[NSCharacterSet illegalCharacterSet]];
int i = 0;
while (![scanner isAtEnd]) {
BOOL scanned = [scanner scanString:#"%#" intoString:NULL];
if (scanned) {
if (i < [myKeyArray count]) {
[result appendString:[myKeyArray objectAtIndex:i]];
i++;
} else {
//Handle error: Number of format specifiers doesn't
//match number of keys in array...
}
}
NSString *chunk = nil;
[scanner scanUpToString:#"%#" intoString:&chunk];
if (chunk) {
[result appendString:chunk];
}
}
Use: stringByAppendingString
Here's an example on how to use it:
NSString *someString = #"String";
someString = [someString stringByAppendingString:[NSString stringWithFormat:#"%#",variable1]];
someString = [someString stringByAppendingString:[NSString stringWithFormat:#"%#",variable2]];
someString = [someString stringByAppendingString:[NSString stringWithFormat:#"%#",variable3]];
...and so on
If you have an array of keys which you want to put in a string:
NSString *string = #"And the keys are:\n";
for(int i = 0; i < [array count]; i++)
{
NSString *thisKey = (NSString *)[array objectAtIndex:i];
string = [string stringByAppendingString:[NSString stringWithFormat:#"Key number %d is %#",i,thisKey]];
}

NSMutableArray of Objects

First off I am very new to Objective C and iPhone programming. Now that that is out of the way. I have read through most of the Apple documentation on this and some third party manuals.
I guess I just want to know if I'm going about this the correct way ...
- (NSMutableArray *)makeModel {
NSString *api = #"http://www.mycoolnewssite.com/api/v1";
NSArray *namesArray = [NSArray arrayWithObjects:#"News", #"Sports", #"Entertainment", #"Business", #"Features", nil];
NSArray *urlsArray = [NSArray arrayWithObjects:
[NSString stringWithFormat:#"%#/news/news/25/stories.json", api],
[NSString stringWithFormat:#"%#/news/sports/25/stories.json", api],
[NSString stringWithFormat:#"%#/news/entertainment/25/stories.json", api],
[NSString stringWithFormat:#"%#/news/business/25/stories.json", api],
[NSString stringWithFormat:#"%#/news/features/25/stories.json", api], nil];
NSMutableArray *result = [NSMutableArray array];
for (int i = 0; i < [namesArray count]; i++) {
NSMutableDictionary *objectDict = [NSMutableDictionary dictionary];
NSString *name = (NSString *)[namesArray objectAtIndex:i];
NSString *url = (NSString *)[urlsArray objectAtIndex:i];
[objectDict setObject:name forKey:#"NAME"];
[objectDict setObject:url forKey:#"URL"];
[objectDict setObject:#"NO" forKey:#"HASSTORIES"];
[result addObject:objectDict];
}
return result;
}
The output of the result is ...
(
{
HASSTORIES = NO;
NAME = News;
URL = "http://www.mycoolnewssite.com/api/v1/news/news/25/stories.json";
},
{
HASSTORIES = NO;
NAME = Sports;
URL = "http://www.mycoolnewssite.com/api/v1/news/sports/25/stories.json";
},
{
HASSTORIES = NO;
NAME = Entertainment;
URL = "http://www.mycoolnewssite.com/api/v1/news/entertainment/25/stories.json";
},
{
HASSTORIES = NO;
NAME = Business;
URL = "http://www.mycoolnewssite.com/api/v1/news/business/25/stories.json";
},
{
HASSTORIES = NO;
NAME = Features;
URL = "http://www.mycoolnewssite.com/api/v1/news/features/25/stories.json";
}
)
Any insight would be appreciated ;-)
It looks fine. There can be some minor improvements if you care.
1.
[NSString stringWithFormat:#"%#/news/news/25/stories.json", api]
can be replaced by
[api stringByAppendingString:#"/news/news/25/stories.json"]
if there's no chance the api appears in the middle or accepts other arguments.
2.
NSString *name = (NSString *)[namesArray objectAtIndex:i];
NSString *url = (NSString *)[urlsArray objectAtIndex:i];
The explicit cast is unnecessary. An id can be implicitly casted to and from other ObjC objects.
3.
You could use a convenient method -dictionaryWithObjectsAndKeys: to construct the dictionary in one-shot, so you don't need a temperary dictionary:
[result addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:
name, #"NAME",
url, #"URL",
#"NO", #"HASSTORIES", nil]];
4. (optional)
This transform is not useful if the function is not a hot spot.
Since the arrays are only used locally, it's more efficient to use a C array.
static const int arraySize = 5;
NSString* namesCArray[] = {#"News", #"Sports", #"Entertainment", #"Business", #"Features"};
NSString* urlsCArray[arraySize];
urlsArray[0] = [api stringByAppendingString:#"/news/news/25/stories.json"];
...
for (int i = 0; i < arraySize; ++ i) {
...
NSString* name = namesCArray[i];
NSString* url = urlsCArray[i];
...
}
this removes the repeated -count and -objectAtIndex: calls which is very slow compared with direct element access.
5. (optional)
This transform is not useful if the array is short.
You could use fast-enumeration to loop over an ObjC container:
int i = 0;
for (NSString* name in namesArray) {
NSString* url = [urlsArray objectAtIndex:i];
...
++ i;
}
6.
Usually we use [NSNumber numberWithBool:NO] to represent a boxed true/false value, instead of a string #"NO". NSNumber is also used a lot whenever a primitive number (int, float, etc.) cannot be used (e.g. to be stored in an NSArray). I don't know if your API explicitly requires a string NO, so it may not unsuitable for you.