Чтение и хранение данных большого шестнадцатеричного файла на языке C - PullRequest
1 голос
/ 18 июня 2020

Мне нужно прочитать большой файл Intel Hex, и в зависимости от типа данных мне нужно сохранить данные в строковом / символьном массиве для дальнейшего использования. Ниже приведен код, я использую кусок для чтения строки из шестнадцатеричного файла, используя data_type для проверки типа данных в строке чтения, sub для хранения проанализированных данных из строки и finaldata, чтобы продолжать добавлять данные по мере чтения. Однако проблема заключается в размере, максимальный размер массива символов составляет 65535 (поправьте меня, если я ошибаюсь), но мои данные составляют около 80000 байт (120K символов). Как я могу с этим справиться (используя C язык)? или лучше перейду на C ++ или C#? Заранее благодарим за любую помощь / понимание, которое вы можете предоставить.

Изменить: данные в шестнадцатеричном формате из файла выглядят следующим образом:: 020000 04 0200F1: 10C000 00 814202D8BFF32F8F10BD441C42E8004366 Мне нужно для чтения этих данных построчно и на основе типа данных (выделено жирным шрифтом, 04 в первой строке, 00 во второй), если это 00, проанализировать данные из следующего байта (байт после типа данных) и прочитать до конца, кроме последнего байт (который является контрольной суммой). Затем перейдите к следующей строке, если тип данных 00, проанализируйте данные и добавьте их к ранее прочитанным данным (конкатенация строк), поэтому переменная должна хранить большой объем окончательных данных (это я, где я борюсь, как чтобы хранить такой большой объем данных в одной переменной)?

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

int main(void)
{
    FILE *fp;
    fp = fopen(*filename, "rb");
    if(fp == NULL) {
        perror("Unable to open file!");
        exit(1);
    }

    char chunk[128];
    char sub[128];

    char finaldata[65535];
    finaldata[0] = '\0';
    // Store the chunks of text into a line buffer
    size_t len = sizeof(chunk);

    while(fgets(chunk, sizeof(chunk), fp) != NULL) {
        //fputs(chunk, stdout);
        int a=0;

        if((chunk[7] == '0') && (chunk[8] == '0')) {
            size_t length = strlen(chunk);

            while (a < (length-13)) {
                sub[a]=chunk[9+a];
                a++;

            }
        }
        strcat(finaldata, sub);
        fputs(finaldata, stdout);
        memset(sub,0,sizeof(sub));
         printf("\n\n");

    }

    fclose(fp);

    printf("\n\nMax line size: %zd\n", len);

    return 0;
}

1 Ответ

1 голос
/ 19 июня 2020

Вы говорите:

читать до конца, кроме последнего байта (который является контрольной суммой)

, но если я применяю :10C00000814202D8BFF32F8F10BD441C42E8004366, ваш код

    int a=0;

    if((chunk[7] == '0') && (chunk[8] == '0')) {
        size_t length = strlen(chunk);

        while (a < (length-13)) {
            sub[a]=chunk[9+a];
            a++;
        }
    }

sub values ​​814202D8BFF32F8F10BD441C42E8004, поэтому вы удаляете 366 в конце строки, а не только 66


Из вашего примечания

при определении массива символов с помощью функции mallo c (), какой размер мне следует указать, поскольку я не знаю точного размера?

Если вы хотите свернуть все подстроки в одной строке, один из способов - начать с массива размером 1 для нулевого завершающего символа, а затем увеличить его на строку в строке, используя malloc. Например:

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

int main(int argc, char ** argv)
{
  if (argc != 2) {
    fprintf(stderr, "Usage: %s <file>\n", *argv);
    exit(1);
  }

  FILE *fp = fopen(argv[1], "rb");

  if (fp == NULL) {
    perror("Unable to open file!");
    exit(1);
  }

  size_t sz = 0; /* without counting the char for \n */
  char * finaldata = malloc(1);
  char chunk[128];

  while (fscanf(fp, " %127s", chunk) == 1) {
    if((chunk[7] == '0') && (chunk[8] == '0')) {
      if (strlen(chunk) != 43) {
        fprintf(stderr, "unexpected line '%s'\n", chunk);
        exit(1);
      }

      chunk[41] = 0; /* remove two last chars */

      char * s = realloc(finaldata, sz + 32 +1); /* + block + \n */

      if (s == NULL) {
        fputs("not enough memory", stderr);
        free(finaldata); /* for valgrind etc */
        exit(1);
      }

      finaldata = s;
      strcpy(finaldata + sz, chunk + 9);
      sz += 32;
    }
  }

  fclose(fp);
  finaldata[sz] = '\0';

  /* debug */
  puts(finaldata);

  free(finaldata); /* for valgrind etc */

  return 0;
}

Я использую fscanf, чтобы обойти возможные пробелы, включая новую строку, до и после части, которой нужно управлять. В формате " %127s" обратите внимание на пробел перед '%' и 127, который равен 128 минус 1, чтобы оставить место для завершающего нуля символа.

Компиляция и выполнение:

pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ cat f
:020000040200F1
:10C00000814202D8BFF32F8F10BD441C42E8004366
:020000040200F1
:10C00000123456789abcdef0123456789abcdef012
pi@raspberrypi:/tmp $ ./a.out f
814202D8BFF32F8F10BD441C42E80043123456789abcdef0123456789abcdef0
pi@raspberrypi:/tmp $ 
...