我有一个使用NSData对象加载的二进制文件。有没有办法在二进制数据中找到一系列字符,例如'abcd',并返回偏移而不将整个文件转换为字符串?似乎它应该是一个简单的答案,但我不知道该怎么做。有什么想法吗?
我在iOS 3上这样做,所以我没有-rangeOfData:options:range:
可用。
我打算把这个奖励给十六奥托以表示strstr。我去找了C函数strstr的源代码并重写它以在固定长度的Byte数组上工作 - 顺便说一下,它与char数组不同,因为它不是null终止的。这是我最终得到的代码:
- (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;
}
这会返回一个指针,指向第一次出现的字节,我正在寻找的东西,在缓冲区中,应该包含字节的字节数组。
我称之为:
// data is the NSData object
const Byte *bytes = [data bytes];
Byte* index = [self offsetOfBytes:tag inBuffer:bytes ofLength:[data length]];
答案 0 :(得分:14)
将您的子字符串转换为NSData
对象,并使用rangeOfData:options:range:
在较大的NSData
中搜索这些字节。确保字符串编码匹配!
在iPhone上,如果没有,您可能需要自己动手。 C函数strstr()
将为您提供指向缓冲区中第一次出现模式的指针(只要它们都不包含空值!),而不是索引。这是应该完成工作的功能(但没有承诺,因为我还没有尝试过实际运行它......):
- (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;
}
这类似于O(nm),其中n是缓冲区长度,m是子串的大小。它被编写为与NSData
一起使用有两个原因:1)这就是你手边的东西,2)这些对象已经封装了实际的字节和缓冲区的长度。
答案 1 :(得分:1)
如果您正在使用Snow Leopard,一种方便的方法是NSData中的新-rangeOfData:options:range:方法,它返回第一次出现的数据的范围。否则,您可以使用其-bytes方法自行访问NSData的内容以执行您自己的搜索。
答案 2 :(得分:1)
我遇到了同样的问题。 与建议相比,我以相反的方式解决了这个问题。
首先,我重新格式化数据(假设您的NSData存储在var rawFile中):
NSString *ascii = [[NSString alloc] initWithData:rawFile encoding:NSAsciiStringEncoding];
现在,您可以使用NSScanner类轻松地执行字符串搜索,例如'abcd'或任何您想要的内容,并将ascii字符串传递给扫描程序。也许这不是很有效,但它也可以工作,直到-rangeOfData方法也可用于iPhone。