I cannot get NSScanner to properly scan data into my application. The data is in the form of an ASCII file with each datum on a separate line. Additionally, the data can be empty, and thus just an empty line. So the data file looks something like this… 19.250 25.062 21.250 14.875 21.875
40.062 75.188 27.120 26.170
23.320 11.000 16.250 8.000 6.375 6.375 14.250 25.375
The code that I am using to load this is float value; NSString *key; id myObject; NSArray *arrayOfKeys = [NSArray arrayWithObjects:@”foo1”, @”foo2”, @”foo3”, nil] NSEnumerator *e = [arrayOfKeys objectEnumerator];
NSString *aString = [NSString stringWithCString:[data bytes] length:[data length]]; // The data is the file as passed into -loadDataRepresentation: ofType
NSScanner *aScanner = [NSScanner scannerWithString:aString]; [aScanner setCharactersToBeSkipped:[NSCharacterSet whitespaceCharacterSet]];
myObject = Object alloc] init];
while ( key = [e nextObject]) { if ([aScanner scanFloat:&value]) { [myObject takeValue:[[[NSNumber numberWithFloat:value] forKey:key]; } else { [myObject setUseData:FALSE forKey:key]; } }
You never said what the code does. It’s obvious what it’s supposed to do, but you just said it’s “not working”. How does it not work, what does it do?
My bad. It loads the first data point, and then doesn’t load any others. Looking at [aScanner scanLocation] it looks like on the second iteration the location goes to a very large number, what I can only assume is the end of the data file, without finding any other float values. —- Here is a variation that does what you wish. I changed the code slightly to make it command-line tool for demonstration, but that doesn’t affect the logic:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSCharacterSet *newlineCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"\n"];
float value;
NSString *key;
id myObject;
NSArray *arrayOfKeys = [NSArray arrayWithObjects:@"foo1", @"foo2", @"foo3", nil];
NSEnumerator *e = [arrayOfKeys objectEnumerator];
NSData *data = [NSData dataWithContentsOfFile:@"/Users/AUser/Projects/ScannerMalfunction/TheData.txt"];
NSString *aString = [NSString stringWithCString:[data bytes] length:[data length]];
NSScanner *aScanner = [NSScanner scannerWithString:aString];
[aScanner setCharactersToBeSkipped:[NSCharacterSet whitespaceCharacterSet]];
myObject = [[NSMutableDictionary alloc] init];
while ( key = [e nextObject])
{
if ([aScanner scanFloat:&value])
{
[myObject takeValue:[NSNumber numberWithFloat:value] forKey:key];
}
else
{
[myObject takeValue:[NSNull null] forKey:key];
}
[aScanner scanUpToCharactersFromSet:newlineCharacterSet intoString:nil]; // Find the newline
[aScanner setScanLocation:([aScanner scanLocation] + 1) ]; // Skip the newline
}
NSLog(@"%@", myObject);
[pool release];
return 0; }
Your original code fails because the scanner can’t get past the newline following the first float. You set the scanner to skip whitespace only, so you must account for the newline.
aburgh