2009-12-02 1 views
8

NSData 객체를 사용하여로드 한 이진 파일이 있습니다. 바이너리 데이터 내에서 'abcd'문자 시퀀스를 찾고 전체 파일을 문자열로 변환하지 않고 오프셋을 반환하는 방법이 있습니까? 그것은 단순한 대답이어야하는 것처럼 보입니다, 그러나 나는 그것을하는 방법을 모르겠습니다. 어떤 아이디어?이진 데이터에서 문자 문자열 찾기

iOS 3에서이 작업을 수행하므로 -rangeOfData:options:range:을 사용할 수 없습니다.

저는 strstr을 제안하기 위해 이것을 16 Otto에게 수여 할 것입니다. 나는 C 함수 strstr에 대한 소스 코드를 찾아 고정 길이의 바이트 배열에서 작업하도록 다시 작성했다. 이것은 null 배열이 아니기 때문에 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]]; 
+0

offsetOfBytes : inBuffer : ofLength :에 대해 게시 한 코드에는 데이터에 실제로 null이 포함될 수있는 경우 많은 문제가 발생합니다 (원래 strstr()이 너무 많음). 최소한이 함수는 얼마나 길어야할지 모르기 때문에 바이트 길이를 전달해야합니다. –

+0

안녕하세요. 의견을 보내 주셔서 감사합니다. ofLength : 매개 변수의 바이트에 대한 길이를 전달하므로 어떤 의미인지 확실하지 않습니다. 감사. –

+0

2 바이트 포인터로 전달되지만 한 길이 만 전달합니다. 이것은 여러분의 코드가'bytes'와'buffer'가 얼마나 오래 있는지를 알 수 없다는 것을 의미합니다. 즉, 여러분이 검색에서 그들 중 하나의 끝에서 벗어날 위험이 있음을 의미합니다. –

답변

14

NSData 객체에 문자열을 변환하고, rangeOfData:options:range:을 사용 NSData 큰에 그 바이트를 검색합니다. 문자열 인코딩이 일치하는지 확인하십시오!

iPhone에서 사용할 수없는 곳에서는 직접해야 할 수도 있습니다. C 함수 strstr()은 (null도 포함하지 않는 한) 버퍼 내에서 패턴의 첫 번째 항목에 대한 포인터를 제공하지만 색인은 제공하지 않습니다. 다음 함수는 (내가 그것을 실행 실제로 시도하지 않은 때문에 ...하지만 약속) 일을 할 것이있다 :

- (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; 
} 

이 n은입니다 O (㎚), 같은에서 실행 버퍼 길이, m은 부분 문자열의 크기입니다. NSData과 작동하도록 작성된 이유는 1) 사용자가 가지고있는 것, 2) 실제 바이트와 버퍼 길이를 모두 캡슐화 한 객체입니다.

+1

나는 rangeofData : options : range : method가없는 iPhone에서이 작업을 수행하고 있다고 언급 했어야합니다. 비록 그것이 한 경우에 완전한 응답 일 것입니다. –

+0

차가움. 나는 당신의 코드를 시도하고 그것이 어떻게되는지 보게 될 것이다. 도와 줘서 고마워. –

+3

업데이트 : rangeOfData는 iOS 4부터 사용 가능합니다. – steipete

1

Snow Leopard를 사용하는 경우 편리한 방법은 데이터 조각의 첫 번째 항목 범위를 반환하는 NSData의 new -rangeOfData : options : range : 메서드입니다. 그렇지 않으면 -bytes 메서드를 사용하여 NSData의 내용에 직접 액세스하여 자신 만의 검색을 수행 할 수 있습니다.

+0

좋은 지적입니다. 나는 -rangeOfData : options : range :가 10.6에 추가되었다는 것을 알지 못했다. –

+1

아이폰에서이 방법을 사용하고 있기 때문에 사용할 방법이 없습니다. 어떤 C 함수를 사용하여 내가 찾고있는 문자 부분 문자열을 -bytes 메서드에서 얻은 버퍼와 비교할 수 있습니까? 어떤 아이디어? –

1

나는 동일한 문제가있었습니다. 제안과 비교하여 다른 방법으로 해결했습니다. 와 데이터 (당신을 NSData가 var에 rawFile에 저장되어있는 가정)

첫째, 내가 포맷 : 당신은 쉽게 'ABCD'하거나 NSScanner 클래스를 사용하여 원하는대로와 같은 문자열 검색을 지금

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

할 수 ascii 문자열을 스캐너에 전달합니다. 아마 이것은 효율적이지는 않지만, -rangeOfData 메서드를 iPhone에서 사용할 수있을 때까지 작동합니다.

+0

답변 해 주셔서 감사합니다. 질문에 언급 된 나의 기준 중 하나는 "전체 파일을 문자열로 변환하지 않고"따라서 이것이 나를위한 실행 가능한 솔루션이 아니기 때문입니다. 지금 당장 내 원래의 질문을 확인해 보았습니다. 모든 데이터를 복사 할 필요없이 잘 작동합니다. NSData 객체의 바이트를 반복하여 필요한 문자 시퀀스를 찾고 첫 번째 항목을 찾으면 배열의 해당 위치에 대한 포인터를 반환합니다. –

+0

예. 알겠습니다. 진정한 요점은 그러한 전환의 비용을 이해하는 것이고, 저는 이것에 대한 단서가 없습니다. 그것을 애플에게 요청하는 것이 유용 할 수있다. 포럼에서도 찾아야한다. :-) – Andy