Ios 在二进制数据中查找字符串

Ios 在二进制数据中查找字符串,ios,objective-c,c,cocoa-touch,nsdata,Ios,Objective C,C,Cocoa Touch,Nsdata,我有一个使用NSData对象加载的二进制文件。是否有一种方法可以在该二进制数据中定位字符序列“abcd”,并返回偏移量,而无需将整个文件转换为字符串?似乎这应该是一个简单的答案,但我不知道怎么做。有什么想法吗 我在iOS 3上执行此操作,因此我没有可用的-rangeOfData:options:range: 我将把这个奖颁给16个奥托,因为他推荐了strstr。我找到了C函数strstr的源代码,并将其重写为固定长度的字节数组——这与字符数组不同,因为它不是以null结尾的。以下是我最后得到的代

我有一个使用NSData对象加载的二进制文件。是否有一种方法可以在该二进制数据中定位字符序列“abcd”,并返回偏移量,而无需将整个文件转换为字符串?似乎这应该是一个简单的答案,但我不知道怎么做。有什么想法吗

我在iOS 3上执行此操作,因此我没有可用的
-rangeOfData:options:range:

我将把这个奖颁给16个奥托,因为他推荐了strstr。我找到了C函数strstr的源代码,并将其重写为固定长度的字节数组——这与字符数组不同,因为它不是以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;
}

将子字符串转换为
NSData
对象,然后使用在较大的
NSData
中搜索这些字节。确保字符串编码匹配

在iPhone上,如果没有,你可能必须自己做。C函数
strstr()
将为您提供一个指针,指向缓冲区中第一个出现的模式(只要它们都不包含null!),但不指向索引。这里有一个函数应该可以完成这项工作(但没有承诺,因为我还没有尝试实际运行它……):

-(NSUTEGER)索引数据:(NSData*)针形索引数据:(NSData*)干草堆
{
常量void*needleBytes=[needleBytes];
常量void*haystackBytes=[haystackBytes];
//遍历缓冲区的长度,查找与开始匹配的字节
//我们可以在结尾跳过(|针|-1)字节,因为我们不能
//有一根比针本身短的火柴
对于(i=0;i<[haystack length]-[Pineer length]+1;i++)
{
//当针的字节仍与haystack的字节匹配时,遍历针的字节
//从i开始;如果我们走到针的末端,我们就找到了一根火柴
整数j=0;
而(j<[针长度]&&needbytes[j]==haystackBytes[i+j])
{
j++;
}
如果(j==[针长度])
{
返回i;
}
}
返回NSNotFound;
}

它以O(nm)的形式运行,其中n是缓冲区长度,m是子字符串的大小。它是为使用NSData而编写的,原因有两个:1)这就是您手头上的数据,2)这些对象已经封装了实际字节和缓冲区的长度。

如果您使用的是雪豹,一种方便的方法是新的-rangeOfData:options:range:method,它返回一段数据第一次出现的范围。否则,您可以使用-bytes方法自己访问NSData的内容来执行自己的搜索。

我也遇到了同样的问题。 与建议相比,我以相反的方式解决了这个问题

首先,我使用以下格式重新格式化数据(假设您的NSData存储在var rawFile中):


现在,您可以使用NSScanner类轻松执行字符串搜索,如“abcd”或任何您想要的内容,并将ascii字符串传递给扫描仪。也许这并不是很有效,但在-rangeOfData方法也适用于iPhone之前,它是有效的。

好的观点。我没有注意到-rangeOfData:options:range:只在10.6中添加了。所以我没有这个方法,因为我在iPhone上做了这个。您将使用什么C函数来比较我正在寻找的字符子字符串和从-bytes方法获得的缓冲区?有什么想法吗?我应该提到我是在没有rangeofData:options:range:method的iPhone上这样做的。如果是的话,那将是一个完美的答案。酷。我将试用你的代码,看看它是如何运行的。再次感谢您的帮助。更新:rangeOfData从iOS 4开始提供。感谢您的回复。我在问题中提出的标准之一是“不将整个文件转换为字符串”,因此这对我来说不是一个可行的解决方案。现在检查我原来的问题,看看我提出的解决方案。它运行良好,无需复制任何数据。我只是在NSData对象的字节上迭代,寻找我需要的字符序列,然后在找到第一个匹配项时返回一个指向数组中该位置的指针。真正的问题是理解这种转换的成本,我对此一无所知。向苹果公司询问这方面的情况可能会有用。。。也必须开始在他们的论坛中查找。:-)如果您的数据真的可以包含null(原始strstrstr()剩下的太多),那么您为offsetOfBytes:inBuffer:ofLength:发布的代码将有很多问题。至少,您需要传入字节的长度,因为这个函数不知道它应该是多长。谢谢你的反馈。我以ofLength:参数传递字节的长度,所以我不确定您的意思。谢谢。您传入的是两个字节指针,但只有一个长度。这意味着您的代码不可能知道两个代码< >字节和<代码>缓冲区< /代码>多长时间,这意味着您有可能在搜索过程中跑出其中一个结束。请考虑将您的解决方案重新发布为下面的答案。我不想编辑它来删除它,以避免隐藏有用的信息,但我相信你知道(现在,如果不是在发布时),解决方案作为答案比放在问题正文中更好。
// data is the NSData object
const Byte *bytes = [data bytes];
Byte* index = [self offsetOfBytes:tag inBuffer:bytes ofLength:[data length]];
- (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;
}
NSString *ascii = [[NSString alloc] initWithData:rawFile encoding:NSAsciiStringEncoding];