2009-10-09 150 views
2

嘿。我试图编写一个小程序,它将在最后一次出现“0xFF 0xC0 0x00 0x11”后读取后面的四个字节,这些字节可以很容易地转换为二进制或十进制。目的是在该十六进制模式的最后一次出现之后的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; 
} 

的问题是我不知道如何从缓冲存储器递归阅读和使用最近读变量作为一个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; 
} 

如果last_needle不为空,可以打印出last_needle+4 ...

+2

'memmem()'函数未由POSIX标准化,但在Linux和AIX上可用,但在MacOS X(10.5)或Solaris 10上不可用。 – 2009-10-09 06:40:51

+1

对于没有memmem实现的用户,我将其留作练习读者... – 2009-10-09 06:43:47

+0

将memmem()似乎是可在OSX https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/memmem.3.html 我也可以用man memmem看到它 (OSX 10.11.6) – Chris 2016-11-16 21:45:26

0

可以使用在C/C fscanf函数++如果数据是ASCII编码。如果没有,你将不得不编写你自己的函数来做到这一点。简单的方法是从文件中读取N个字节,然后搜索字符串中所需的模式,然后继续,直到EOF。

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

另外,如果你打算做什么您已经阅读的大小,请确保您释放malloced缓冲区对象,以避免泄漏后。

+0

的权利..龟etc上一个r + b文件将返回二进制整数值是? – Supernovah 2009-10-09 04:38:00

+0

,因为它似乎正在返回垃圾值。我如何才能将上一个fgetc结果与二进制8位字节进行比较? – Supernovah 2009-10-09 04:40:31

+0

我不使用fgetc,但我认为它从内部文件位置的当前位置返回一个字节。 – ldog 2009-10-09 04:42:03

1

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

在这种情况下,你应该能够手动设计这一点。对于更复杂的要求,请看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 */ 
    } 
} 

末,你留下了5个字节lastBytes这是最后一次右后五个字节你找到searchChars