2016-03-01 46 views
0

我目前正在試圖做一個程序,操縱從命令行參數分析的二進制文件。該程序會在輸出文件的開頭插入一個無符號整型數據後,將二進制文件(input.bin)複製到另一個文件(output.bin)中。命令都按這樣的:C二進制I/O程序問題

$./padder input.bin output.bin 50 

但是我的輸出給了我:

Source successfully written to destination after padding by 53 

我遇到的第一個問題是,53不是int我通過在墊(插入)。我遇到的第二個問題是,在對我的input.bin文件和我的output.bin文件進行十六進制轉儲之後,它們是相似的,但不完全是我想要的。

進制打印input.bin:

0000000 3231 3433 3635 3837 3039 000a   
000000b 

進制打印output.bin:

0000000 3231 3433 3635 3837 3039 000a 0000 0000 
0000010 0000 0000 0000 0000 0000 0000 0000 0000 
* 
000002c 

任何人都可以給我一些見解?我是新來的文件I/O和相當新的,但在C.沒有老到任何幫助表示讚賞

源代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <fcntl.h> 

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

    if(argc != 4){ 
     printf("ERROR: INCORRECT AMOUNT OF ARGUMENTS!!!\n"); 
    } else { 

     FILE *input = fopen(argv[1], "rb"); 
     if(input == NULL){ 
      perror("INPUT FILE OPEN"); 
      exit(EXIT_FAILURE); 
     } 

     FILE *dest = fopen(argv[2], "wb"); 
     if(dest == NULL){ 
      perror("DEST FILE OPEN"); 
      exit(EXIT_FAILURE); 
     } 

     unsigned int *pad_val = (unsigned int *)argv[3]; 
     unsigned char *pad = (unsigned char *) pad_val; 

     size_t n, m; 
     unsigned char buff[4096]; 
     do{ 
      n = fread(buff, 1, sizeof buff, input); 
      if(n){ 
       m = fwrite(buff, 4, n, dest); 
       rewind(dest); 
       m = fwrite(&pad, 1, n, dest); 
      } else { 
       m = 0; 
      } 
     } while((n > 0) && (n == m)); 

     if(m){ 
      perror("copy"); 
     } 
     printf("Source successfully written to destination after padding by %u\n", *pad); 
     fclose(input); 
     fclose(dest); 
    } 
    return 0; 
} 
+3

這裏是一個提示:在ASCII中,'5''的數值爲53。 – EOF

回答

2

你是什麼意思精確地在開頭插入一個unsigned int的輸出文件

您的代碼當前複製文件的開頭,但寫入的字節數爲讀取的字節數的4倍,可能會讀取buff的末尾,並嘗試用未指定的數據覆蓋開頭,通過從內存中讀取的方式調用未定義的行爲pad的結尾。

如果要在命令行中指定一個整數值的小端二進制表示形式的4個字節作爲一串數字插入,則可以在文件副本的開頭以這種方式修改程序:

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <fcntl.h> 

int main(int argc, char *argv[]) { 
    if (argc != 4) { 
     printf("ERROR: INCORRECT AMOUNT OF ARGUMENTS!!!\n"); 
     return 1; 
    } 
    FILE *input = fopen(argv[1], "rb"); 
    if (input == NULL) { 
     perror("INPUT FILE OPEN"); 
     exit(EXIT_FAILURE); 
    } 
    FILE *dest = fopen(argv[2], "wb"); 
    if (dest == NULL) { 
     perror("DEST FILE OPEN"); 
     exit(EXIT_FAILURE); 
    } 
    unsigned int pad_val = strtoul(argv[3], NULL, 0); 

    fputc((pad_val >> 0) & 255, dest); 
    fputc((pad_val >> 8) & 255, dest); 
    fputc((pad_val >> 16) & 255, dest); 
    fputc((pad_val >> 24) & 255, dest); 

    size_t n; 
    unsigned char buff[4096]; 

    while ((n = fread(buff, 1, sizeof buff, input)) > 0) { 
     if (fwrite(buff, 1, n, dest) != n) { 
      perror("fwrite"); 
      break; 
     } 
    } 
    fclose(input); 
    if (fclose(dest)) { 
     perror("fclose"); 
    } else { 
     printf("Source successfully written to destination after padding by %u\n", pad_val); 
    } 
    return 0; 
} 
+0

實際上這不會乾淨地編譯,並且可以爲目標文件輸出argv [3]的無效值。 – user3629249

+0

其中一個問題:1)'unsigned int'不一定是4個字節。建議使用'uint32_t'。 4字節的無符號整型的輸出將會更容易寫成:'fwrite(&pad_val,sizeof(pad_val),1,dest);' – user3629249

+0

@ user3629249:確實'unsigned int'可能有多於或少於4個字節,但不建議使用'fwrite'編寫'uint32_t',因爲它不是endian中立的。將4個字節分開寫入,並進行明確的移位,並以相同的方式讀取並組合它們,這樣更具可移植性。 Little endian架構在桌面上占主導地位,但在計算機世界的其他地方卻不佔優勢。 – chqrlie