2014-07-07 65 views
0

我試圖掃描一個文件,尋找1MB的JPEG文件,這些文件將被連續存儲。我的方法是創建一個結構來匹配前4個字節和JPEG簽名,如果是true,則將整個512緩衝區寫入指定文件,直到找到另一個jpeg簽名,然後創建一個新文件。下面的代碼創建2個文件,由於前幾個字節不是jpeg簽名的一部分,因此兩個文件都不可讀。任何想法,我出錯了?我嘗試了我的if語句的變體,我在那裏測試了簽名,但到目前爲止還沒有運氣。匹配JPEG簽名

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 

typedef uint8_t BYTE; 

typedef struct 
{ 
    BYTE first; 
    BYTE second; 
    BYTE third; 
    BYTE fourth; 
} 
JPGTEST; 

int main(int argc, char* argv[]) 
{ 

    FILE* inptr = fopen("card.raw", "r"); 

    if (inptr == NULL) 

    { 

     printf("Could not open file\n"); 

     return 2; 

    } 

    FILE* outptr; 

    //initialize jpeg count and variable for filename 
    int count = 0; 
    char name[8]; 

    //allocate memory 
    char buffer[512]; 
    JPGTEST myjpg; 
    int is_open = 0; 

    while (fread(&buffer, 512, 1, inptr) != 0) 
    { 

     //test first 4 bytes to see if jpeg 
     fread(&myjpg, sizeof(JPGTEST), 1, inptr); 

     //if match, name and write to file 

     if (myjpg.first == 0xff && myjpg.second == 0xd8 && myjpg.third == 0xff && (myjpg.fourth == 0xe0 || myjpg.fourth == 0xe1)) 
     { 
      sprintf(name, "%03d.jpg", count); 
      if (is_open == 0) 
      {   
       outptr = fopen(name, "w"); 
       fwrite(buffer, sizeof(buffer),1,outptr); 
       is_open = 1; 
      } 
      if (is_open == 1) 
      {   
       fclose(outptr); 
       outptr = fopen(name, "w"); 
       fwrite(buffer, sizeof(buffer),1,outptr); 
       count++; 
      } 

     } 
     else 
     { 
      if (is_open == 1) 
      { 
       fwrite(buffer, sizeof(buffer),1,outptr); 
      } 
     } 
    } 
    fclose(inptr); 
    fclose(outptr); 
    return 0; 
} 
+0

從看一眼,似乎myBuffer包含字節0-511,myjpeg包含字節512-515。提示:不要做第二次閱讀。檢查緩衝區的前4個字節。 (或者寫myjpeg,接着是X字節數X = ??) – enhzflep

回答

1

更換你的第二個FREAD與下面的循環中:

 memcpy((void *)&myjpg, (void *) buffer, sizeof(JPGTEST)); 

,包括在你的代碼文件string.h頭文件的memcpy功能。

你在做什麼錯誤的是,在讀取第一個512之後,你沒有對它們進行任何使用,而是再次讀取4個字節而不檢查前面讀取的512個字節的前4個字節。

+0

謝謝,那就工作了。猜猜我在檢查前兩次移動指針。 – Andy

+2

建議'memcpy(&myjpg,buffer,sizeof myjpg);',因爲代碼可以丟棄不需要的'(void *)'和IMO,'sizeof var'比'sizeof(type)更容易維護' – chux

0

問題是您在讀入buffer後沒有重置文件位置指示器,請使用fseek。即:

//test first 4 bytes to see if jpeg 
    fseek (inptr, SEEK_SET, 0); 
    fread(&myjpg, sizeof(JPGTEST), 1, inptr); 

這將會爲您提供JPG頭的myjpg測試:

sizeof (myjpg): 4 
first: ff second: d8 third ff fourth: e0 

然而,這也將導致你將不得不返工邏輯的問題。根據其他答案的建議,簡單閱讀buffer中的值會更好。

2

您正在打開文件文本模式。您需要二進制模式,而不是將其打開:

FILE* inptr = fopen("card.raw", "rb"); 

outptr = fopen(name, "wb"); 

除此之外,您呼叫fread()太多次了,只是一般沒有正確管理文件。

嘗試更多的東西這個:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 

typedef uint8_t BYTE; 

#pragma pack(push, 1) 
typedef struct 
{ 
    BYTE first; 
    BYTE second; 
    BYTE third; 
    BYTE fourth; 
} 
JPGTEST; 
#pragma pack(pop) 

int main(int argc, char* argv[]) 
{ 
    FILE* inptr = fopen("card.raw", "rb"); 
    if (inptr == NULL) 
    { 
     printf("Could not open file\n"); 
     return 2; 
    } 

    FILE* outptr = NULL; 

    //initialize jpeg count and variable for filename 
    int count = 0; 
    char name[8]; 

    //allocate memory 
    char buffer[512]; 
    JPGTEST myjpg; 

    while (fread(buffer, sizeof(buffer), 1, inptr) > 0) 
    { 
     //test first 4 bytes to see if jpeg 
     memcpy(&myjpg, buffer, sizeof(JPGTEST)); 

     //if match, name and write to file 
     if ((myjpg.first == 0xff) && (myjpg.second == 0xd8) && (myjpg.third == 0xff) && ((myjpg.fourth == 0xe0) || (myjpg.fourth == 0xe1))) 
     { 
      if (outptr != NULL) 
      {   
       fclose(outptr); 
       outptr = NULL; 
      } 

      ++count; 
      sprintf(name, "%03d.jpg", count); 

      outptr = fopen(name, "wb"); 
     } 

     if (outptr != NULL) 
      fwrite(buffer, sizeof(buffer), 1, outptr); 
    } 

    fclose(inptr); 

    if (outptr != NULL) 
     fclose(outptr); 

    return 0; 
} 
+0

此解決方案導致seg故障。我很確定我需要測試當前正在寫入的文件是否仍然打開(即仍然寫入20個512KB塊之一)。但是,感謝您收到輸出文件的最終Null檢查。忘了測試一下。 – Andy

+1

問題是'outptr'沒有初始化爲NULL,所以第一次循環迭代試圖寫入未打開的文件。我糾正了這一點。 –

+0

謝謝。因此,檢查'outptr = NULL'是否會執行我的'is_open'變量的工作,儘管它乾淨得多。 – Andy