在C中搜索二进制模式(读取缓冲的二进制文件)

时间:2009-10-09 04:25:55

标签: c binary design-patterns match buffered

嘿那里。我正在尝试编写一个小程序,它将在最后一次出现“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来与我的二进制/十六进制/十进制进行比较。

我该怎么做?

5 个答案:

答案 0 :(得分:8)

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 ...

答案 1 :(得分: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后的五个字节

答案 2 :(得分:1)

就个人而言,我会使用一次吞下一个字符的函数。该函数将使用有限状态机进行简单的正则表达式匹配,将详细信息保存在静态局部变量或参数块结构中。您需要两个子块 - 一个用于部分匹配状态,一个用于最后一个完全匹配 - 每个子块根据需要指示相关位置或值。

在这种情况下,您应该能够手动设计。有关更复杂的要求,请查看Ragel

答案 3 :(得分:0)

如果数据以ascii编码,则可以在C / C ++中使用fscanf函数。如果不是,你将不得不编写自己的功能来完成这项工作。简单的方法是从文件中读取N个字节,在字节字符串中搜索所需的模式,然后继续直到EOF。

您的代码实际上一次读取整个文件(如果您要查找的行靠近文件顶部,则不需要。)您的代码将文件作为字节数组存储在堆上(char等效于一个字节在C ++中)缓冲区指向内存中连续数组的开始。操纵缓冲区数组就像操纵任何其他数组一样。

此外,如果您在阅读完大小后打算执行任何,请确保释放malloced缓冲区对象以避免泄漏。

答案 4 :(得分:0)

使用magic_open()和magic_print() 更安全易用