Buscar cadena de caracteres en datos binarys

Tengo un file binary que he cargado utilizando un object NSData. ¿Hay alguna manera de localizar una secuencia de caracteres, 'abcd', por ejemplo, dentro de esos datos binarys y devolver el desplazamiento sin convertir todo el file a una cadena? Parece que debería ser una respuesta simple, pero no estoy seguro de cómo hacerlo. ¿Algunas ideas?

Estoy haciendo esto en iOS 3, así que no tengo -rangeOfData:options:range: available.

Voy a otorgar esta a Sixteen Otto por sugerir strstr. Fui y encontré el código fuente de la function C strstr y lo reescribí para que funcione en una matriz Byte de longitud fija, que por cierto es diferente de una matriz char, ya que no está terminada de forma nula. Aquí está el código con el que terminé:

 - (Byte*)offsetOfBytes:(Byte*)bytes inBuffer:(const Byte*)buffer ofLength:(int)len; { Byte *cp = bytes; Byte *s1, *s2; if ( !*buffer ) return bytes; int i = 0; for (i=0; i < len; ++i) { s1 = cp; s2 = (Byte*)buffer; while ( *s1 && *s2 && !(*s1-*s2) ) s1++, s2++; if (!*s2) return cp; cp++; } return NULL; } 

Esto devuelve un puntero a la primera aparición de bytes, lo que estoy buscando, en el búfer, la matriz de bytes que debería contener bytes.

Lo llamo así:

 // data is the NSData object const Byte *bytes = [data bytes]; Byte* index = [self offsetOfBytes:tag inBuffer:bytes ofLength:[data length]]; 

Convierta su subcadena en un object NSData y busque esos bytes en el NSData más NSData utilizando rangeOfData:options:range: ¡Asegúrate de que las codificaciones de cadenas coincidan!

En el iPhone, donde no esté disponible, es posible que deba hacerlo usted mismo. La function C strstr() le dará un puntero a la primera aparición de un patrón dentro del búfer (¡mientras no contengan nulos!), Pero no el índice. Aquí hay una function que debería hacer el trabajo (pero no hay promises, ya que no he intentado realmente ejecutarlo …):

 - (NSUInteger)indexOfData:(NSData*)needle inData:(NSData*)haystack { const void* needleBytes = [needle bytes]; const void* haystackBytes = [haystack bytes]; // walk the length of the buffer, looking for a byte that matches the start // of the pattern; we can skip (|needle|-1) bytes at the end, since we can't // have a match that's shorter than needle itself for (NSUInteger i=0; i < [haystack length]-[needle length]+1; i++) { // walk needle's bytes while they still match the bytes of haystack // starting at i; if we walk off the end of needle, we found a match NSUInteger j=0; while (j < [needle length] && needleBytes[j] == haystackBytes[i+j]) { j++; } if (j == [needle length]) { return i; } } return NSNotFound; } 

Esto se ejecuta en algo así como O (nm), donde n es la longitud del búfer, ym es el tamaño de la subcadena. Está escrito para trabajar con NSData por dos razones: 1) eso es lo que parece tener en la mano, y 2) esos objects ya encapsulan tanto los bytes reales como la longitud del búfer.

Si está utilizando Snow Leopard, una forma conveniente es el nuevo range -rangeOfData: options: range: método en NSData que devuelve el range de la primera aparición de una pieza de datos. De lo contrario, puede acceder a los contenidos de NSData usted mismo utilizando su método byby para realizar su propia búsqueda.

Yo tuve el mismo problema. Lo resolví al revés, en comparación con las sugerencias.

Primero, reformateo los datos (suponga que su NSData está almacenado en var rawFile) con:

 NSString *ascii = [[NSString alloc] initWithData:rawFile encoding:NSAsciiStringEncoding]; 

Ahora, puede realizar fácilmente búsquedas de cadenas como 'abcd' o lo que quiera con la class NSScanner y pasar la cadena ascii al escáner. Tal vez esto no sea realmente eficiente, pero funciona hasta que el método -rangeOfData esté disponible para iPhone también.