2009-10-09 7 views
2

안녕하세요. 나는 "0xFF 0xC0 0x00 0x11"의 마지막 발생 이후 네 바이트 또는 십진수로 쉽게 변환 할 수있는 4 바이트를 읽는 작은 프로그램을 작성하려고합니다. 그 목적은 그 16 진수 패턴의 마지막 발생 다음 2-5 바이트가 JPEG 파일의 폭과 높이를 나타내는 것입니다.C에서 바이너리 패턴 검색 (버퍼 된 바이너리 파일 읽기)

#include <stdio.h> 

int main() { 
    FILE * pFile; 
    long lSize; 
    char * buffer; 
    size_t result; 

    pFile = fopen ("pano8sample.jpg" , "rb"); 
    if(pFile==NULL){ 
    fputs ("File error",stderr); 
    exit (1); 
    } 

    fseek (pFile , 0 , SEEK_END); 
    lSize = ftell (pFile); 
    rewind (pFile); 

    printf("\n\nFile is %d bytes big\n\n", lSize); 

    buffer = (char*) malloc (sizeof(char)*lSize); 
    if(buffer == NULL){ 
    fputs("Memory error",stderr); 
    exit (2); 
    } 

    result = fread (buffer,1,lSize,pFile); 
    if(result != lSize){ 
    fputs("Reading error",stderr); 
    exit (3); 
    } 

    //0xFF 0xC0 0x00 0x11 (0x08) 

    //Logic to check for hex/binary/dec 

    fclose (pFile); 
    free (buffer); 
    return 0; 
} 

문제는 내가 재귀 적으로 버퍼 메모리에서 읽어 내 바이너리/진수/DEC에 대해 비교하는 int로 가장 최근에 읽은 변수를 사용하는 방법을 모르는 것입니다.

어떻게하면됩니까?

답변

6
byte needle[4] = {0xff, 0xc0, 0x00, 0x11}; 
byte *last_needle = NULL; 
while (true) { 
    byte *p = memmem(buffer, lSize, needle, 4); 
    if (!p) break; 
    last_needle = p; 
    lSize -= (p + 4) - buffer; 
    buffer = p + 4; 
} 

, 내가 한 번에 하나 개의 문자를 삼킨 기능을 사용하는 것, 개인적으로

+2

'memmem()'함수는 POSIX에 의해 표준화되지 않았지만 리눅스와 AIX에서 사용 가능하지만 MacOS X (10.5) 나 Solaris 10에서는 사용 가능하지 않습니다. –

+1

memmem 구현이없는 사람들을 위해 독자 ... –

+0

memmem()이 OSX에서 사용 가능한 것으로 보입니다 https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/memmem.3.html I 남자 memmem을 사용하여 그것을 또한보십시오 (OSX 10.11.6) – Chris

0

데이터가 ascii로 인코딩 된 경우 C/C++에서 fscanf 함수를 사용할 수 있습니다. 그렇지 않으면, 당신은 이것을 할 당신 자신의 함수를 작성해야 할 것이다. 간단한 방법은 N 바이트의 파일을 읽고, 원하는 패턴의 바이트 문자열을 검색 한 다음 EOF까지 계속 진행하는 것입니다.

코드는 실제로 전체 파일을 한꺼번에 읽습니다 (찾고있는 줄이 파일의 맨 위에 있으면 불필요합니다). 코드는 파일을 힙에 바이트 배열로 저장합니다 (char는 C++의 바이트) 버퍼에 메모리의 인접 배열 시작 위치에 대한 포인터가 있습니다. 다른 배열을 조작하는 것처럼 버퍼 배열을 조작하십시오.

크기를 읽은 후을 수행하려는 경우 누출을 방지하려면 malloced 버퍼 객체를 해제해야합니다. last_needle가 null가 아닌 경우

+0

바로 ..는 fgetc에서 찾기 r + b 파일은 2 진 정수 값을 반환합니다. 예? – Supernovah

+0

은 정크 값을 반환하는 것으로 보입니다. 마지막 fgetc 결과를 바이너리 8 비트 바이트와 어떻게 비교할 수 있습니까? – Supernovah

+0

fgetc를 많이 사용하지는 않지만 내부 파일 위치의 현재 위치에서 바이트를 반환한다고 생각합니다. – ldog

1

... last_needle+4를 인쇄 할 수 있습니다. 이 함수는 유한 상태 머신을 사용하여 간단한 정규식 일치를 수행하고 세부 사항을 정적 로컬 변수 또는 매개 변수 블록 구조로 저장합니다. 부분 일치 상태에 대한 하위 블록과 마지막 완전 일치에 대한 하위 블록 두 개가 필요합니다. 각 하위 블록은 각각 필요한 위치 또는 값을 나타냅니다.

이 경우 수동으로 설계 할 수 있어야합니다. 보다 복잡한 요구 사항은 Ragel을 참조하십시오.

2

전체 파일을 메모리로 읽는 대신, 약간의 상태 시스템을 사용합니다. 내 C는 약간 녹슨이지만 :

끝에
char searchChars[] = {0xFF,0xC0,0x00,0x11}; 
char lastBytes[5]; 
int pos = 0; int curSearch = 0; 
while(pos <= lSize) { 
    curChar = getc(pfile); pos++;   /*readone char*/ 

    if(curChar == searchChars[curSearch]) { /* found a match */ 
     curSearch++;      /* search for next char */ 
     if(curSearch > 3) {     /* found the whole string! */ 
      curSearch = 0;     /* start searching again */ 
      read = fread(lastBytes,1,5,pfile); /* read 5 bytes */ 
      pos += read;      /* advance position by how much we read */ 
     } 
    } else { /* didn't find a match */ 
     curSearch = 0;      /* go back to searching for first char */ 
    } 
} 

, 당신이 바로 마지막 시간 이후 다섯 바이트 lastBytes 5 바이트 남겨 당신은 searchChars에게

관련 문제