Поиск двоичного шаблона в C (чтение буферизованного двоичного файла) - PullRequest
2 голосов
/ 09 октября 2009

Привет. Я пытаюсь написать небольшую программу, которая будет читать четыре следующих байта после последнего появления «0xFF 0xC0 0x00 0x11», которые можно легко преобразовать в двоичный или десятичный. Цель состоит в том, чтобы 2-5 байтов после последнего вхождения этого шестнадцатеричного шаблона представляли ширину и высоту файла JPEG.

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

Проблема в том, что я не знаю, как рекурсивно читать из буферизованной памяти и использовать последнюю переменную чтения как int для сравнения с моим двоичным / hex / dec.

Как мне это сделать?

Ответы [ 4 ]

8 голосов
/ 09 октября 2009
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;
}

Если last_needle не равно нулю, вы можете распечатать last_needle+4 ...

2 голосов
/ 09 октября 2009

вместо чтения всего файла в память, я бы использовал немного конечного автомата. Мой 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 */
    }
 }

в конце, у вас осталось 5 байтов в lastBytes, которые представляют собой пять байтов сразу после последнего поиска searchChars

1 голос
/ 09 октября 2009

Лично я бы использовал функцию, которая проглатывает один символ за раз. Функция будет использовать конечный автомат для простого сопоставления с регулярным выражением, сохраняя детали либо в виде статических локальных переменных, либо в виде структуры параметров Вам нужны два подблока - один для состояния с частичным совпадением и один для последнего полного соответствия - каждый с указанием соответствующих позиций или значения по мере необходимости.

В этом случае вы сможете создать это вручную. Для более сложных требований, посмотрите на Ragel .

0 голосов
/ 09 октября 2009

Вы можете использовать функцию fscanf в C / C ++, если данные закодированы в ascii. Если это не так, вам придется написать свою собственную функцию, которая будет делать это. Простой способ - прочитать N байтов из файла, найти в байтовой строке искомый шаблон и продолжить до EOF.

Ваш код фактически считывает весь файл сразу (ненужно, если искомая строка находится в верхней части файла.) Ваш код сохраняет файл в куче в виде байтового массива (символ эквивалентен байту в C ++) с буфером указатель на начало непрерывного массива в памяти. Управляйте буферным массивом так же, как вы управляете любым другим массивом.

Кроме того, если вы намерены сделать что-нибудь после того, как прочитали размер, убедитесь, что вы освободили объект буферизованного буфера, чтобы избежать утечки.

...