2016-03-01 4 views
0

В настоящее время я пытаюсь создать программу, которая манипулирует двоичным файлом, проанализированным из аргументов командной строки. Программа вводит двоичный файл (input.bin), копирует его в другой файл (output.bin) после вставки беззнакового int в начале выходного файла. Команда идет как например:C Проблемы с двоичной программой ввода-вывода

$./padder input.bin output.bin 50 

Однако мой выход дает мне:

Source successfully written to destination after padding by 53 

первый вопрос, который я имею что 53 не Int Я прошел в раздуть (вставить). Вторая проблема заключается в том, что после hexdumping как моего файла input.bin, так и моего файла output.bin они похожи, но не совсем то, что я хочу.

HexDump input.bin:

0000000 3231 3433 3635 3837 3039 000a   
000000b 

HexDump output.bin:

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

Может кто-нибудь дать мне некоторое представление? Я новичок в файл ввода/вывода и довольно новый, но не закаленный 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

Что вы имеете в виду именно вставки без знака 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'. вывод без знака int из 4 байтов будет гораздо проще записываться как: 'fwrite (& pad_val, sizeof (pad_val), 1, dest);' – user3629249

+0

@ user3629249: действительно 'unsigned int' может иметь более или менее 4 байтов, но писать даже 'uint32_t' с' fwrite' не рекомендуется, потому что он не является нейтральным по отношению к ней. Более портативно писать 4 байта отдельно, с явными сдвигами и читать их и комбинировать их одинаково. Маленькие архитектуры endian преобладают на рабочем столе, но не на остальной части вычислительного мира. – chqrlie

Смежные вопросы