【问题标题】:How can I save a struct with pointers(what is pointed to aswell) to a file - C如何将带有指针的结构(也指向什么)保存到文件中-C
【发布时间】:2015-03-17 05:55:53
【问题描述】:

我正在尝试创建一个程序,该程序可以将指向的信息也保存在文件中。所以我可以加载它并在以后使用它。

这是我的两个结构体:

typedef struct{
    char name[11];
    char efternamn[11];
}person;

typedef struct{
    int numbofpersons;
    person * personList;
}personGOD;

personGOD controller;
int choice;
do
{
    printf("(1) to Initialize x amount of persons\n"
           "(3) to Save\n"
           "(5) Load controller\n");
    scanf("%d", &choice);
    switch (choice)
    {

    case 1  :
        InitializePersons(&controller);
        break;
    case 3  :
        SavePersonsToFile(&controller);
        break;

    case 5 :
        LoadController(&controller);
        break;
    }
}
while(flag);

这里是加载、保存、初始化函数:

void InitializePersons(personGOD* controller)
{
    int amount, i;
    printf("How many persons to be created");
    fscanf(stdin, "%d", &amount);

    controller->personList = (person*)calloc(amount, sizeof(person));

    for(i=0; i < amount; i++)
    {
        printf("Name: ");
        fscanf(stdin, "%s", controller->personList[i].name);

        printf("lastname: ");
        fscanf(stdin, "%s", controller->personList[i].efternamn); //eftername=lastname
    }
    controller->numbofpersons = amount; // update how many persons we current have
}

void SavePersonsToFile(personGOD* controller)
{

    FILE* fileptr;
    if((fileptr = fopen("C:\\Users\\x\\Desktop\\OpenStruct\\persons", "r+b"))== NULL)
    {
        fprintf(stderr, "Error opening file: %s\n", strerror( errno ));
        exit(0);
    }

    if(fwrite(controller, sizeof(personGOD), 1, fileptr)<1)
        fprintf(stderr, "%s\n", strerror( errno ));
    fclose(fileptr);

}

void LoadController(personGOD* controller)
{
    FILE* fileptr;
    if((fileptr = fopen("C:\\Users\\x\\Desktop\\OpenStruct\\persons", "r+b"))== NULL)
    {
        fprintf(stderr, "Error opening file: %s\n", strerror( errno ));
        exit(0);
    }
    if(fread(controller, sizeof(personGOD), 1, fileptr)<1){
                fprintf(stderr, "%s\n", strerror( errno ));
    }
    fclose(fileptr);
}

当我保存->关闭程序->打开->加载时会发生什么,numofpersons 是正确的,而 personList 将指向不再分配的内存并崩溃。

很难在谷歌上搜索如何实现这一点。

如何保存和恢复指向的数据

【问题讨论】:

  • 是的,没那么简单。指针通常只是内部对应于内存位置的 64(或 32)位数字,因此当您将 personGOD 写出时,它只会写入 numbofpersons(以二进制字节为单位),然后是指针 8(或 4)字节的二进制数据,并且可能在两者之间添加了一些结构填充。您需要手动对数据进行显式编码和解码。
  • 谷歌“序列化”。
  • 我建议使用一些 json(或 xml,如果你愿意)库来写和读回你的数据,除非你绝对需要二进制文件 Firmat。

标签: c file struct restore


【解决方案1】:

您通常永远不想将原始指针数据写入文件,因为如果您稍后重新运行程序(或在另一台机器上,使用另一个编译器等),则无法保证对象将具有相同的地址。

因此,您需要单独编写字段,因为 fwrite 不知道您要写入什么类型的数据。这由 fwrite 类型为const void* 的第一个参数指示。

一个例子(减去错误处理):

fwrite(&controller->numberofpersons, sizeof(controller->numberofpersons), 1, fileptr);
fwrite(controller->personList, sizeof(*controller->personList), controller->numberofpersons, fileptr);

对于读取文件,您使用相同的逻辑:

fread(&controller->numberofpersons, sizeof(controller->numberofpersons), 1, fileptr);
controller->personList = calloc(controller->numberofpersons, sizeof(*controller->personList);
fread(controller->personList, sizeof(*controller->personList), controller->numberofpersons, fileptr);

这个解决方案存在字节序问题,所以它不是完全可移植的,但那是另一回事了。

【讨论】:

    【解决方案2】:

    您无法保存指向文件的内存指针并将其读回。内存是非常动态的,使用此方法可以保证您获得内存冲突。在任何现代操作系统中,这都行不通。您正在做的是 inmemoryDB 的粗略解决方案,但为了持久性,您需要写入实际数据和@加载时间,在将数据读取(解析)到内存后重新创建数据结构。

    【讨论】:

    • 有什么建议可以在哪里或我可以阅读如何解决这个问题?
    【解决方案3】:

    最好不要重新发明轮子。有许多工具能够执行序列化任务。选择什么取决于你。就个人而言,我更喜欢 SQLite,因为它可移植、灵活、相对轻量级、没有依赖关系并且易于集成到 C 源代码中。然而,这意味着将您的数据重写为关系表并使用您可能不喜欢(想要)的 SQL 等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-14
      • 1970-01-01
      • 1970-01-01
      • 2010-09-25
      • 2012-07-16
      • 1970-01-01
      • 2013-05-30
      相关资源
      最近更新 更多