【问题标题】:Reading and Storing large hex file data using C language使用 C 语言读取和存储大型 hex 文件数据
【发布时间】:2020-10-08 16:32:08
【问题描述】:

我需要读取一个大型 Intel Hex 文件并根据数据类型,需要将数据存储在字符串/字符数组中以供以后使用。下面是代码,我正在使用块从 hex 文件中读取行,使用 data_type 检查读取行中的数据类型,使用 sub 存储行中的解析数据,使用 finaldata 在读取时继续添加数据。但是问题是大小,最大字符数组大小是 65535(如果我错了,请纠正我),但我的数据大约是 80,000 字节(120K 个字符)。 我该如何解决这个问题(使用 C 语言)?或者如果我切换到 C++ 或 C# 会更好? 提前感谢您提供的任何帮助/见解。

编辑:文件中的十六进制数据如下所示: :020000040200F1 :10C00000814202D8BFF32F8F10BD441C42E8004366 我需要逐行读取此数据并根据数据类型(以粗体显示,第一行为 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;
}

【问题讨论】:

  • 最大字符数组大小为 65535(如果我错了,请纠正我) - 是的,你错了。 stackoverflow.com/questions/9386979/…
  • 当你需要一个大数组时不要将它放入堆栈,使用动态内存分配(malloc
  • 是的,C++ 会为您提供随时可用的“容器类”,您可能会非常感激。您可以使用“直接 C”完成工作 - 使用 bruno 的建议使用 malloc,但只需“从现成的适当容器类中获取”并知道它确实很方便将像宣传的那样工作。 “因为懒惰是一种美德,”我现在在所有使用 C 的情况下都使用 C++。(而且我更频繁地使用其他解释型语言。)
  • BTW - “80,000 字节(120K 字符)。” -听起来怪怪的。你的“字符”是否小于字节?
  • strcmp ("00", data_type) 具有未定义的行为,数组长度仅为 2,并且您将其 2 个元素设置为没有空终止字符。在你的循环中做strcat(finaldata, sub); 是没有代价的,至少每次都保存结束位置/ptr,为什么要使用中间数组 sub

标签: c arrays char c-strings


【解决方案1】:

你说:

读取直到结束,除了最后一个字节(这是校验和)

但如果我申请 :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++;
        }
    }

sub814202D8BFF32F8F10BD441C42E8004,因此您删除了行尾的 366 而不仅仅是 66


根据你的评论

当使用 malloc() 函数定义 char 数组时,由于我不知道确切的大小,我应该放什么大小?

如果你想折叠一个字符串中的所有子字符串,一种方法是从一个大小为 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 $ 

【讨论】:

  • 感谢详细解答,我现在得到了动态内存分配。我有一个问题,“finaldata = s;”为什么它只增加了“finaldata”字符串的大小,为什么没有将“s”(空字符串)的内容复制到“finaldata”中?
  • 关于 var s 是“干净”的,非干净版本是直接做finaldata = realloc(finaldata, sz + 32 +1);。该表单只会增加 finaldata 的大小,因此在需要添加新部分之后,执行 strcpy(finaldata + sz, chunk + 9);
  • finaldata = s; 用另一个指针分配一个指针,这不是深拷贝。两个变量中保存的地址相同后(一个指针就是一个地址)
  • 我还发现 hex 文件中有一行长度不是 43 而是正确的数据类型,所以我创建了一个整数来检查“块”的长度,然后我使用该变量来删除校验和并正确调整大小并读取数据。感谢您的帮助,我会将其标记为已回答。
猜你喜欢
  • 2012-08-14
  • 1970-01-01
  • 2014-12-13
  • 1970-01-01
  • 2018-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多