【问题标题】:How can I read a large set of data from a file into either a pointer to a structure or array of a structure in C如何从文件中读取大量数据到 C 中的结构指针或结构数组中
【发布时间】:2022-08-17 06:06:02
【问题描述】:

我有一个具有已知密钥的数据文件,也就是说,它有许多具有相同属性的条目(设备),并且我在代码中有这个结构来捕获它。

struct deviceData{
  int id;
  char serial[10];
  float temperature;
  float speed; 
  long timestamp; 
}

struct deviceData fileItems;

ID 占 4 个字节,序列码占 10 个字节,温度和速度占 4 个字节,时间戳占 8 个字节。总共 30 个字节。

我想要实现的是能够阅读所有这些条目并以我能最快的方式运行计算。

我最初想做的是简单地创建一个巨大的数组来捕获所有条目,但这会导致错误。
其次,我想到了从指向该结构的指针分配空间并将整个文件读取到该结构。这在执行中有效,但我在处理数据时遇到了麻烦。可能是我在基本面方面的差距。

我目前正在查看的方式是循环读取我使用 fread() 捕获单个条目的读数,处理该条目,然后移动文件以将下一个条目放入缓冲区。 像这样的东西:

fread(&fileItems, 30, 1, filename)

但发生的情况是,当我查看实际读取的内容时,我看到 ID 和序列码已正确读取,但以下数据点是垃圾。读了一点关于它我遇到了一些关于填充的东西,我不完全理解,但修复似乎是让我的 char 数组 100 这似乎适用于第一个条目,但我怀疑它会导致问题随后的读数,因为它使我的计算中断。

我在这里有点困难,因为我尝试的每一个策略似乎都有一些奇怪的东西。如果我至少可以指出正确的方向,我至少会知道我正在为正确的事情努力。

  • 数据如何存储在文件中。它是原始二进制文件吗?文本?如果原始二进制文件可以提供一些记录的十六进制转储(例如)
  • 您是否检查过该结构是否会占用 30 个字节的空间?查看Structure Alignment 了解更多信息。
  • 确保以二进制模式打开文件(假设文件包含原始数据),在您的结构中使用具有已知、正确大小的类型。你可能还想让你的结构打包
  • 所以十六进制数据将是...01 00 00 00 4E 46 32 43 2D 37 49 56 33 00 41 B3 33 33 42 86 FA E1 52 92 C5 61 00 00 00 00 然后如果你解析得到 id: 1, serial: NF2C-7IV3, temp: 22.4, speed: 67.49, timestamp 1640338002. 然后下一个以 ID 开头太和值 2
  • @lulle 你对一个打包的结构是什么意思?

标签: arrays c pointers debugging structure


【解决方案1】:

如果您只是想逐条记录处理一组数据,您可能可以利用定义结构的方法,然后将文件中的数据读取到结构中,然后处理数据。为了使事情保持一致,将数据作为结构存储在二进制文件中是有意义的。以下是一段代码 sn-p 创建一些示例数据,然后按照项目的精神对其进行处理。

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

struct deviceData{
  int id;
  char serial[10];
  float temperature;
  float speed;
  long timestamp;
};

struct deviceData fileItems;

void create_data(char * file_name)
{
    FILE* fp = fopen(file_name, "wb");
    if(!fp)
    {
        printf("\n\tFile open error\n");
        return;
    }

    for (int i = 0; i < 10; i++)
    {
        fileItems.id = i + 20000 + i * 3;
        sprintf(fileItems.serial, "SN%d", fileItems.id);
        fileItems.temperature = 166.0 + i;
        fileItems.speed = 2400.0;
        fileItems.timestamp = 20220830;
        fwrite(&fileItems, sizeof(struct deviceData), 1, fp);
    }

    fclose(fp);
}

void read_data(char *file_name)
{
    FILE* fp = fopen(file_name, "rb");

    if(!fp)
    {
        printf("\n\tFile open error\n");
        return;
    }

    while(fread(&fileItems, sizeof(struct deviceData), 1, fp))
    {
        printf("ID. . .  . . . .: %d\n", fileItems.id);
        printf("Serial number. .: %s\n", fileItems.serial);
        printf("Temparature. . .: %f\n", fileItems.temperature);
        printf("Speed. . . . . .: %f\n", fileItems.speed);
        printf("Timestamp. . . .: %ld\n", fileItems.timestamp);
    }
}

int main()
{
    create_data("device.dat");      /* Create some sample data to be read      */
    read_data("device.dat");        /* Read and print the data to the terminal */
    return 0;
}

设备数据的存储可能会发生在其他一些监控程序中,但是对于这个 sn-p,包含了一次性功能以产生一些数据进行处理。

分析该代码,看看它是否符合您的项目精神。

【讨论】:

    猜你喜欢
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多