代码之家  ›  专栏  ›  技术社区  ›  Matt Long

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

  •  8
  • Matt Long  · 技术社区  · 15 年前

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

    我在iOS 3上做这个,所以我没有 -rangeOfData:options:range: 可用。

    我要把这个奖励给16个奥托,因为他推荐了StrStr。我找到了C函数strstr的源代码,并重写了它,以便在固定长度的字节数组上工作——这与char数组正好不同,因为它不是以空结尾的。下面是我最后得到的代码:

    - (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]];
    
    3 回复  |  直到 9 年前
        1
  •  14
  •   Sixten Otto    15 年前

    将子字符串转换为 NSData 对象,并在较大的 操作文件数据 使用 rangeOfData:options:range: . 确保字符串编码匹配!

    在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(n m),其中n是缓冲区长度,m是子串的大小。它是为工作而写的 操作文件数据 有两个原因:1)这就是您手头上的东西,2)这些对象已经封装了实际字节和缓冲区的长度。

        2
  •  1
  •   user155959    15 年前

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

        3
  •  1
  •   Andy    15 年前

    我也有同样的问题。 与建议相比,我用另一种方法解决了这个问题。

    首先,我用以下方法重新格式化数据(假设您的nsdata存储在var rawfile中):

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

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