0

I have an NSData object which contains some data I need. What I wanted to do is to find out the position of data "FF D8" (start of JPEG data)

How can I achieve work like this?

Andrew Chang
  • 1,289
  • 1
  • 18
  • 38
  • 1
    Use the `-bytes` method to get a pointer to the data, then do a loop that looks for `0xff`, and if it finds it, check if it is followed by `0xd8`. – zneak Aug 28 '13 at 00:52
  • This is one way. But I wonder if there is a way with shorter coding, like NSString's rangeOfString: Oops, I just found NSData's method `rangeOfData:options:range:`. Seemed works to me? – Andrew Chang Aug 28 '13 at 01:00

2 Answers2

9

First get the range, then get the data:

// The magic start data object is only created once safely and 
// then reused each time
static NSData* magicStartData = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
  static const uint8_t magic[] = { 0xff, 0xd8 };
  magicStartData = [NSData dataWithBytesNoCopy:(void*)magic length:2 freeWhenDone:NO];
});

// assume data is the NSData with embedded data
NSRange range = [data rangeOfData:magicStartData options:0 range:NSMakeRange(0, [data length])];
if (range.location != NSNotFound) {
  // This assumes the subdata doesn't have a specific range and is just everything
  // after the magic, otherwise adjust
  NSData* subdata = [data subdataWithRange:NSMakeRange(range.location, [data length] - range.location)];
}
Jason Coco
  • 77,985
  • 20
  • 184
  • 180
  • Thank you! BTW, is there any way like `static NSdata* magicStartData = [NSData dataWithBytesNoCopy:{0xff, 0xd8} length:2 freeWhenDone:NO];' to make the data to compared constant? As this "FF D8" data need not frequent allocation. – Andrew Chang Aug 28 '13 at 01:38
  • @AndrewChang You could do it with a `dispatch_once` call. I'll update my answer to show that as an example. – Jason Coco Aug 28 '13 at 01:42
  • Wow, I haven't known this function before. Another new knowledge, thank you! – Andrew Chang Aug 28 '13 at 01:44
1

Try NSData rangeOfData:options:range::

    NSData *data = /* Your data here */;

    UInt8 bytes_to_find[] = { 0xFF, 0xD8 };
    NSData *dataToFind = [NSData dataWithBytes:bytes_to_find
                                        length:sizeof(bytes_to_find)];

    NSRange range = [data rangeOfData:dataToFind
                              options:kNilOptions
                                range:NSMakeRange(0u, [data length])];

    if (range.location == NSNotFound) {
        NSLog(@"Bytes not found");
    }
    else {
        NSLog(@"Bytes found at position %lu", (unsigned long)range.location);
    }
eik
  • 2,104
  • 12
  • 15