当我们将结构体存入文件时,如果直接以二进制写入的方式,那么在读取数据时有可能会遇到乱码或者其他解析错误。因此,我们一般采用更加安全和稳定的方式进行结构体与文件的交互,即先将结构体以文本形式编码成字符串,再将字符串写入文件中。在读取时,则需按照约定的格式进行解析,将字符串还原为结构体。
假设我们有一个结构体类型 Person
,包括姓名、年龄、性别等信息,首先可以将结构体转成字符串(以JSON格式为例):
c复制代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <jansson.h> #define FILE_PATH "person_info.txt" typedef struct { char name[20]; int age; char gender[6]; } Person; int main() { // 以JSON格式序列化结构体 Person p = {"zhangsan", 25, "male"}; json_t *json_person = json_pack("{s:s, s:i, s:s}", "name", p.name, "age", p.age, "gender", p.gender); char *str_person = json_dumps(json_person, JSON_COMPACT | JSON_ENSURE_ASCII); // 将序列化后的字符串写入文件 FILE *fp = fopen(FILE_PATH, "w"); if (fp == NULL) { printf("Failed to open file %s\n", FILE_PATH); return -1; } fprintf(fp, "%s\n", str_person); fclose(fp); // 读取文件中的字符串,并解析为结构体 char buffer[1024]; fp = fopen(FILE_PATH, "r"); if (fp == NULL) { printf("Failed to open file %s\n", FILE_PATH); return -1; } fgets(buffer, sizeof(buffer), fp); fclose(fp); json_error_t error; json_t *parsed_json = json_loads(buffer, 0, &error); // 解析JSON字符串 if (!json_is_object(parsed_json)) { fprintf(stderr, "error: JSON format is invalid.\n"); json_decref(json_person); json_decref(parsed_json); return 1; } Person new_p; // 解析JSON对象为Person结构体 json_unpack(parsed_json, "{s:s, s:i, s:s}", "name", new_p.name, "age", &new_p.age, "gender", new_p.gender); printf("name: %s, age: %d, gender: %s\n", new_p.name, new_p.age, new_p.gender); // 释放资源 json_decref(json_person); json_decref(parsed_json); free(str_person); return 0; }
在上述例子中,我们先使用 json_dumps
函数将结构体 p
序列化成为一个JSON格式的字符串 str_person
,然后将其写入文件中。这里注意到,在调用 fprintf()
写入文件时,我们加入了\n
换行符,以便于后续读取操作时更好地处理多行字符串。
接下来,在读取文件时,我们首先定义一个 buffer
数组用于存放读取到的数据。然后使用 fgets()
函数将该文件的第一行读取到 buffer
中,并关闭文件。
接着,我们使用 json_loads
函数解析读取到的 JSON 字符串,并检查是否解析成功。如果解析成功,则根据文件中存储的信息,使用 json_unpack
函数将JSON对象转换为结构体类型,最后打印出得到的新结构体数据。
需要注意的是,这里的 json_t
类型是由第三方库 jansson 提供的,需要先安装并链接该库才能使用。另外,当我们使用字符串作为数据存储时,也需要考虑大小端字节序、字符集编码等因素,以保证数据在不同机器和操作系统之间可移植性。