设为首页 加入收藏

TOP

C中级 数据序列化简单使用和讨论 (二)(一)
2017-10-11 15:46:14 】 浏览:4653
Tags:中级 数据 序列化 简单 使用 讨论

引言  -  一种更好的方式

  其实不管什么语言, 开发框架都会遇到序列化问题. 序列化可以理解为A 和 B 交互的一种协议. 

很久以前利用 printf 和 scanf 的协议实现过一套序列化问题.

  C基础 数据序列化简单使用和讨论

本文在上面基础上运用一种新的尝试. 具体的思路是 利用编译器对结构的统一内存编码方式.

具体实现通过进出栈宏 #pragma pack(push, 1) ... #pragma pack(pop) 设置结构体编译器的编码方式.

#pragma pack(push, 1)
struct person {
    int id;
    char sex;
    int age;
    char name[65];
    double high;
    double weight;
};
#pragma pack(pop)

当编译器解析 struct person 的时候, 采用1字节对齐. 保证结构体编解析后二进制数据是一样的(VS 和 GCC测试过).

这是不同系统间通信的不变量之一.  通过这种序列化的思路. 不妨设计一个验证的Demo如下

window 生产者代码

    // 设置数据, 开始写到测试文件中,再去读取
    struct person per = {
        1, 1, 19, "simplec王志", 179.0, 70.1 
    };

    // 这里开始写数据到文件中. 
    const char * path = "person.txt";
    FILE * txt = fopen(path, "wb");
    if (NULL == txt)
        exit(EXIT_FAILURE);
    fwrite(&per, sizeof(struct person), 1, txt);

    fclose(txt);

linux 使用者代码

    const char * path = "person.txt";
    FILE * txt = fopen(path, "rb");
    if (NULL == txt)
        exit(EXIT_FAILURE);
            
    struct person np; 
    fread(&np, sizeof(struct person), 1, txt);
        
    printf("[%d, %d, %d, %s, %lf, %lf]\n",
        np.id, np.sex, np.age, np.name, np.high, np.weight);
    
    fclose(txt);

实际运行的结果展示.

不知道你是否感到好奇, 为啥最终结果不对呢. 这就扯出了, 编程开发中所有老鸟都必须要面对的坑. "编码统一的坑".

  

  为了将问题表述的更明白, 再来个Demo. sizeofname.c

#include <stdio.h>
#include <wchar.h>
int main(int argc, char * argv[]) { // 系统默认编码, 一共 2 + 3 + 7 + 1 = 13 个 字符 char as[] = "王志 - simplec"; // 采用宽字节, 2字节表示一个字符 wchar_t bs[] = L"王志 - simplec"; // 采用UTF-8编码, 重要 ☆ char cs[] = u8"王志 - simplec"; printf("sizeof as = %zu.\n", sizeof as); printf("sizeof bs = %zu.\n", sizeof bs); printf("sizeof cs = %zu.\n", sizeof cs); return 0; }

在window 上运行结果如下, 我的系统默认是gbk编码(ascii码扩充版). 如果装英文版window默认是utf-8.

中间扯个淡. 我的VS设置中默认是 unix utf-8 有 BOM 文件编码格式. 详细配置可以参照这篇博客 - Visual Studio 默认保存为UTF8编码

在linux上测试结果如下, linux默认UTF-8编码

通过上面你也可以看出来, 主要问题是编码不一致导致了乱码. 最终使fread解析出错. 那么随后就开始解决这个问题.

前言总结

  1. #pragma pack(push, 1) ... #pragma pack(pop) 是一种 C/C++ 系统间直接序列化的一种高效手段

  2. 系统编码推荐统一采用 UTF-8. linux 默认就是, window 中文版是gbk.

下面将提出一种编码统一的方案. 到这里基本可以了, 后面可以选看. O(∩_∩)O哈哈~

 

前言  -  需要一些帮助,刚好我已经做了

  以前有个GNU 的 libiconv 跨平台的库可以解决不同平台的编码问题. 其最近版本对window不再提供直接支持了.

这里我将其继续拉取到window上了搞了一通,最终生成libiconv.lib. 具体可以看下面项目

  libiconv-for-window  https://github.com/wangzhione/libiconv-for-window

工程详细的配置步骤如下

========================================================================
    静态库:libiconv for window 项目概述
========================================================================

/////////////////////////////////////////////////////////////////////////////

当前移植项目基于 GNU 项目 libiconv-1.15 | http://www.gnu.org/software/libiconv/

移植到平台 window 10 14393.953 | Visual Studio 2017 

项目发起人 : simplec - wz | wangzhione@163.com

/////////////////////////////////////////////////////////////////////////////

具体操作思路:
    1. 从官网下载资源 libiconv压缩包, 并解压 [xxx = 解压后的详细path]

    2. 在 $(ProjectDir) 项目目录下, 新建 include 目录
        2.1 将压缩包中 xxx/include/iconv.h.build.in 复制到 include 目录下, 并重名为 iconv.h
        2.2 将 xxx/onfig.h.in 复制到 include 下, 名为 config.h
        2.3 将 xxx/lib 下 所有 *.h and *.def 文件复制到 include 目录下
        2.4 将 xxx/libcharset/include/localcharset.h.build.in 复制到 include 目录下, 并改名

    3. 将 xxx/libcharset/lib/localcharse
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Opencv实现的简易绘图工具 下一篇一些..C#知识点总结

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目