前言
C中对序列化讨论少, 因为很多传输的内容都有自己解析的轮子. 对于序列化本质是统一编码, 统一解码的方式.
本文探讨是一种简单的序列化方案. 保证不同使用端都能解析出正确结果.
在文章一开始, 看一个最简单的序列化代码 如下
#include <stdio.h> #include <stdlib.h> #define _INT_NAME (64) #define _STR_TXT "student.struct" struct student { int id; char sex; int age; char name[_INT_NAME + 1]; double high; double weight; }; // struct student 结构体序列化到文件的方法 static void _student_serialize(struct student* stu, FILE* txt) { fprintf(txt, "%d %c %d %s %lf %lf ", stu->id, stu->sex, stu->age, stu->name, stu->high, stu->weight); } // struct student 结构体反序列化 static void _student_deserialize(struct student* stu, FILE* txt) { fscanf(txt, "%d %c %d %s %lf %lf ", &stu->id, &stu->sex, &stu->age, stu->name, &stu->high, &stu->weight); } // 简单打印数据 static void _student_print(struct student* stu) { static int _idx; printf("%d: %d %c %d %s %lf %lf \n", _idx++, stu->id, stu->sex, stu->age, stu->name, stu->high, stu->weight); } /* * 一种最简单的通用序列化方法 */ int main(int argc, char* argv[]) { FILE* txt = fopen(_STR_TXT, "wb+"); if (NULL == txt) { fprintf(stderr, "fopen " _STR_TXT " error!\n"); return -1; } // 这里写入数据 struct student stu = { 0, 0, 23, "鸣人", 172.23, 64.05 }; _student_print(&stu); // 这里序列化并写入数据到文件 _student_serialize(&stu, txt); // 我们读取这个文件, 先设置文件指针到文件开头 fseek(txt, 0, SEEK_SET); // 开始读取数据 struct student ts; _student_deserialize(&ts, txt); _student_print(&ts); fclose(txt); system("pause"); return 0; }
本质在 自定义编码解码,并利用 scanf和printf 对映关系
// struct student 结构体序列化到文件的方法 static void _student_serialize(struct student* stu, FILE* txt) { fprintf(txt, "%d %c %d %s %lf %lf ", stu->id, stu->sex, stu->age, stu->name, stu->high, stu->weight); } // struct student 结构体反序列化 static void _student_deserialize(struct student* stu, FILE* txt) { fscanf(txt, "%d %c %d %s %lf %lf ", &stu->id, &stu->sex, &stu->age, stu->name, &stu->high, &stu->weight); }
运行结果 如下:
通过这种实现, 是跨平台的. 因为C实现标准和自己定义协议支持
"%d %c %d %s %lf %lf "
最后我们还会讨论这种情况.
正文
1. 一次失败扩展 fscanf -> fread ; fprintf -> fwrite
测试如下, 在window上测试代码 main.c
#include <stdio.h> #include <stdlib.h> #define _INT_NAME (64) #define _STR_TXT "student.struct" struct student { int id; char sex; int age; char name[_INT_NAME + 1]; double high; double weight; }; // struct student 结构体序列化到文件的方法 static void _student_serialize(struct student* stu, FILE* txt) { fwrite(stu, sizeof(*stu), 1, txt); } // struct student 结构体反序列化 static void _student_deserialize(struct student* stu, FILE* txt) { fread(stu, sizeof(*stu), 1, txt); } // 简单打印数据 static void _student_print(struct student* stu) { static int _idx; printf("%d: %d %c %d %s %lf %lf \n", _idx++, stu->id, stu->sex, stu->age, stu->name, stu->high, stu->weight); } /* * 一种最简单的通用序列化方法 */ int main(int argc, char* argv[]) { FILE* txt = fopen(_STR_TXT, "wb+"); if (NULL == txt) { fprintf(stderr, "fopen " _STR_TXT " error!\n"); return -1; } // 这里写入数据 struct student stu = { 0, 0, 23, "鸣人", 172.23, 64.05 }; _student_print(&stu); // 这里序列化并写入数据到文件 _student_serialize(&stu, txt); // 我们读取这个文件, 先设置文件指针到文件开头 fseek(txt, 0, SEEK_SET); // 开始读取数据 struct student ts; _student_deserialize(&ts, txt); _student_print(&ts); fclose(txt); system("pause"); return 0; }