自学内容网 自学内容网

数据格式-个人整理

在整理代码时想到是否有比JSON更好的数据格式没有,然后就了解当下有哪些数据格式。

1.自定义二进制  

        要自己实现,有开发维护需求, 专业度高;效率高。

2.提供序列化和反序列化库的开源协议 

        【如protocol buffers,Thrift】;

        引入第三方库,        

3.文本化协议 

        【如json,xml】 

        传输效率低

 

-----------------------------------------------------------

2024年7月25日  15点05分 ,今天先整理到这,如下已经满足大部分开发使用了

----------------------------------------------------------

数据格式
  1. YAML (YAML Ain't Markup Language): YAML 是一种直观的数据序列化格式,旨在使人类编写和阅读数据变得容易。它使用空白和缩进来表示层次结构,这使得 YAML 文件通常比 JSON 文件更易于阅读和编写。
  2. TOML (Tom's Obvious, Minimal Language): TOML 是另一种轻量级的配置文件格式,设计用于易于阅读和编写。它支持基本的数据类型以及数组和表格,并且具有明确的语法,这使得它非常适合配置文件。
  3. XML (eXtensible Markup Language): XML 是一种标记语言,用于结构化文档和数据。虽然它通常比 JSON 或 YAML 更冗长,但它提供了丰富的结构和命名空间支持,使其在某些领域仍然很受欢迎。
  4. CSV (Comma-Separated Values): CSV 是一种简单的平面文件格式,用于存储表格数据。它非常适合存储和传输数据集,但不适合复杂的嵌套数据结构。
  5. Protocol Buffers: Protocol Buffers 是 Google 开发的一种高效的数据交换格式,它使用二进制格式,因此在传输和解析速度上优于文本格式。虽然它不如 JSON 或 YAML 人性化,但在性能敏感的应用中非常有用。
  6. MessagePack: MessagePack 是一种高效的二进制序列化格式,类似于 Protocol Buffers,但不需要显式的模式定义。它支持多种语言,并且在许多情况下比 JSON 更紧凑。
  7. Properties (Java Properties Format): 这是一种简单的键值对格式,主要用于 Java 应用程序的配置文件。它使用等号 (=) 分隔键和值,使用井号 (#) 表示注释。
  8. INI Files: INI 文件格式是一种简单的配置文件格式,使用节和键值对。它被广泛用于 Windows 应用程序的配置文件。

 9. Avro

 Avro,是指数据序列化的系统,有丰富的数据结构类型、快速可压缩的二进制数据形式。

当Avro数据存储到文件中时,它的模式也随之存储,这样任何程序都可以对文件进行处理。

Avro依赖于模式(Schema)。Avro数据的读写操作是很频繁的,而这些操作都需要使用模式,这样就减少写入每个数据资料的开销,使得序列化快速而又轻巧。这种数据及其模式的自我描述方便于动态脚本语言的使用。

Avro模式是用JSON(一种轻量级的数据交换模式)定义的,这样对于已经拥有JSON库的语言可以容易实现。

原文链接: Avro_百度百科

10.Thrift

Thrift包含一套完整的栈来创建客户端和服务端程序。顶层部分是由Thrift定义生成的代码。而服务则由这个文件客户端和处理器代码生成。在生成的代码里会创建不同于内建类型的数据结构,并将其作为结果发送。协议和传输层运行时库的一部分。有了Thrift,就可以定义一个服务或改变通讯和传输协议,而无需重新编译代码。除了客户端部分之外,Thrift还包括服务器基础设施来集成协议和传输,如阻塞、非阻塞及多线程服务器。栈中作为I/O基础的部分对于不同的语言则有不同的实现。

Thrift支持众多通讯协议:

  • TBinaryProtocol – 一种简单的二进制格式,简单,但没有为空间效率而优化。比文本协议处理起来更快,但更难于调试

  • TCompactProtocol – 更紧凑的二进制格式,处理起来通常同样高效。

  • TDebugProtocol – 一种人类可读的文本格式,用来协助调试。

  • TDenseProtocol – 与TCompactProtocol类似,将传输数据的元信息剥离。

  • TJSONProtocol – 使用JSON对数据编码。

  • TSimpleJSONProtocol – 一种只写协议,它不能被Thrift解析,因为它使用JSON时丢弃了元数据。适合用脚本语言来解析。

支持的传输协议有:

  • TFileTransport – 该传输协议会写文件。

  • TFramedTransport – 当使用一个非阻塞服务器时,要求使用这个传输协议。它按帧来发送数据,其中每一帧的开头是长度信息。

  • TMemoryTransport – 使用存储器映射输入输出。(Java的实现使用了一个简单的ByteArrayOutputStream。)

  • TSocket – 使用阻塞的套接字I/O来传输。

  • TZlibTransport – 用zlib执行压缩。用于连接另一个传输协议。

Thrift还提供众多的服务器,包括:

  • TNonblockingServer – 一个多线程服务器,它使用非阻塞I/O(Java的实现使用了NIO通道)。TFramedTransport必须跟这个服务器配套使用。

  • TSimpleServer – 一个单线程服务器,它使用标准的阻塞I/O。测试时很有用。

  • TThreadPoolServer – 一个多线程服务器,它使用标准的阻塞I/O

原文链接: thrift_百度百科

自定义二进制-简易参考代码

一种简易网络传输数据格式【替代json/xml】_类似json的数据格式-CSDN博客

提供一种简单的key-val数据封装,无需引入库,仅仅是一个简单的类,传输效率效率远高于第3种方式。名为 DatX。

DatX一定程度上只是提供了一种方案,起抛砖引玉的作用,但同时此处提供的DatX代码也是一个完整的,可直接引入工程使用的类。
如果愿意使用,请保留类注释中的作者笔名[hicker]^_^


注意:由于未使用算法优化内存的分配,故每调用一次Put都会重新malloc/free内存。有必要可以自己实现一个内存分配算法


主要接口:
// 添加数据
BOOL Put(char *szKey, int iVal);
BOOL Put(char *szKey, float fVal);
BOOL Put(char *szKey, void *pData, int nData);
// 反序列化
BOOL UnPack(void *pData, int nData);
// 获取第i个key名
char *GetKey(int i);
// 获取key所对应的val,类型为xty
xty operator[](int i);
xty operator[](char *szKey);
// 将返回DatX数据的二进制流,以及大小
void *Bytes();
int Total();

代码如下,只有一个结构体DatX

DatX.h
 

/*************************************************************************
** Desc: 为避免使用json和xml做网络传输,实现一种简单key-val数据类型,
**内存结构如下: [cnt|int_key|xty_key|int_dat|xty|xty_dat]
**cnt_seg: 数据个数段,iCnt,xCnt
**int_key_seg: int/float型key
**xty_key_seg: xty型key
**int_dat: int型数据区
**xty: xty区
**xty_dat: xty.p的数据区
**【注意】DatX会自动将int型key/val保存在xty型key/val前
** Author: hicker@2017-3-19 11:11:57
*************************************************************************/
typedef struct tagDatX
{
tagDatX() :iCnt(0), xCnt(0), __p(NULL), __n(sizeof(iCnt) + sizeof(xCnt)), __p_cnt(NULL), __p_int_key(NULL), __p_xty_key(NULL), __p_int_dat(NULL), __p_xty(NULL), __p_xty_dat(NULL), __z_xty_dat(0){}
tagDatX(void *pData, int nData) 
:iCnt(0), xCnt(0), __p(NULL), __n(sizeof(iCnt) + sizeof(xCnt)), __p_cnt(NULL), __p_int_key(NULL), __p_xty_key(NULL), __p_int_dat(NULL), __p_xty(NULL), __p_xty_dat(NULL), __z_xty_dat(0)
{
UnPack(pData, nData);
}
~tagDatX(){ if (__p) free((void*)__p); }
 
typedef struct tagxty
{
tagxty():p(NULL),l(0){}
char *ToChar(int *nLen = 0){ if (nLen)*nLen = l; return (char*)p; };
int ToInt(){ return l; };
float ToFloat(){ return *((float*)&l); };
 
private:
int p; // xty数据内存偏移量
int l; // xty数据大小
friend tagDatX;
}xty;
 
BOOL Put(char *szKey, int iVal)
{
// 保存旧偏移
save_old_ofs();
 
// 申请新内存
__n += __z_k + __z_i;
__p = (int)malloc(__n);
if (__p == NULL)
{
__p = __p_old;
__n = __n_old;
return FALSE;
}
memset((void*)__p, 0, __n);
iCnt++;
 
// 计算新偏移量
calc_new_ofs();
// __z_xty_dat;
 
 
// 保存旧数据
if (__p_old) save_old_dat();
 
// 保存新数据
((int*)__p_cnt)[0] = iCnt;
((int*)__p_cnt)[1] = xCnt;
strcpy((char*)(__p_int_key + iCnt_old*__z_k), szKey);
*(int*)(__p_int_dat + iCnt_old*__z_i) = iVal;
 
return TRUE;
}
 
BOOL Put(char *szKey, float fVal)
{
return Put(szKey, *(int*)&fVal);
}
 
BOOL Put(char *szKey, void *pData,int nData)
{
// 保存旧偏移
save_old_ofs();
 
// 申请新内存
__n += __z_k + __z_c+nData;
__p = (int)malloc(__n);
if (__p == NULL)
{
__p = __p_old;
__n = __n_old;
return FALSE;
}
memset((void*)__p, 0, __n);
xCnt++;
 
// 计算新偏移量
calc_new_ofs();
__z_xty_dat +=nData; 
 
// 保存旧数据
if (__p_old) save_old_dat();
 
// 保存新数据
((int*)__p_cnt)[0] = iCnt;
((int*)__p_cnt)[1] = xCnt;
strcpy((char*)(__p_xty_key + xCnt_old*__z_k), szKey);
((int*)(__p_xty + __z_x*xCnt_old))[0] = __z_xty_dat_old;
((int*)(__p_xty + __z_x*xCnt_old))[1] = nData;
memcpy((void*)(__p_xty_dat + __z_xty_dat_old), pData, nData);
 
return TRUE;
}
 
BOOL UnPack(void *pData, int nData)
{
// 保存旧偏移
save_old_ofs();
 
// 申请新内存
__n = nData;
__p = (int)malloc(__n);
if (__p == NULL)
{
__p = __p_old;
__n = __n_old;
return FALSE;
}
memcpy((void*)__p, pData, __n);
 
// 解析 iCnt,xCnt
iCnt = ((int*)__p)[0];
xCnt = ((int*)__p)[1];
 
// 计算新偏移量
calc_new_ofs();

// 解析__z_xty_dat
for (int i = iCnt; i < iCnt + xCnt; i++)
__z_xty_dat += ((int*)(__p_xty + i*__z_x))[1];//((*this)[i]).l;
 
return TRUE;
}
 
char *GetKey(int i)
{
if (i < iCnt + xCnt)
{
return (char*)(__p_int_key + (i*__z_k));
}
 
return NULL;
};
 
xty operator[](int i)
{
xty x;
 
if (i < iCnt)
{
x.l = *(int*)(__p_int_dat + (i*__z_i));
}
else if (i < iCnt + xCnt)
{
//memcpy(&x, (void*)(__p_xty+((i-iCnt)*__z_x)), __z_x);
x.p = ((int*)(__p_xty + ((i - iCnt)*__z_x)))[0];
x.l = ((int*)(__p_xty + ((i - iCnt)*__z_x)))[1];
x.p += __p_xty_dat;
}
 
return x;
}
 
xty operator[](char *szKey)
{
xty x;

for (int i = 0; i < iCnt+xCnt; i++)
{
if (strcmp(szKey, (char*)(__p_int_key + (i*__z_k))) == 0)
return (*this)[i];
}
 
return x;
}
 
void *Bytes(){ return (void*)__p; }
int Total(){ return __n; }
 
private:
void save_old_ofs()
{// 保存旧偏移
__p_old = __p;
__n_old = __n;
__p_cnt_old = __p_cnt;
__p_int_key_old = __p_int_key;
__p_xty_key_old = __p_xty_key;
__p_int_dat_old = __p_int_dat;
__p_xty_old = __p_xty;
__p_xty_dat_old = __p_xty_dat;
__z_xty_dat_old = __z_xty_dat;
iCnt_old = iCnt;
xCnt_old = xCnt;
}

void save_old_dat()
{// 保存旧数据
memcpy((void*)__p_cnt, (void*)__p_cnt_old, __z_c);
memcpy((void*)__p_int_key, (void*)__p_int_key_old, __z_k*iCnt_old);
memcpy((void*)__p_xty_key, (void*)__p_xty_key_old, __z_k*xCnt_old);
memcpy((void*)__p_int_dat, (void*)__p_int_dat_old, __z_i*iCnt_old);
memcpy((void*)__p_xty, (void*)__p_xty_old, __z_x*xCnt_old);
memcpy((void*)__p_xty_dat, (void*)__p_xty_dat_old, __z_xty_dat_old);
free((void*)__p_old);
}
 
void calc_new_ofs()
{ // 计算新偏移量
__p_cnt = __p;
__p_int_key = __p_cnt + __z_c;
__p_xty_key = __p_int_key + __z_k*iCnt;
__p_int_dat = __p_xty_key + __z_k*xCnt;
__p_xty = __p_int_dat + __z_i*iCnt;
__p_xty_dat = __p_xty + __z_x*xCnt;
}
public:
int iCnt; // int/float 个数
int xCnt; // xty 个数
 
private:
static const int __z_k = 32; // szKey最大长度
static const int __z_c = sizeof(int) * 2; // 头大小[sizeof(iCnt) + sizeof(xCnt);]
static const int __z_i = sizeof(int); // int大小
static const int __z_x = sizeof(int) * 2; // xty大小[sizeof(xty::p)+sizeof(xty::l)]
 
// 各数据段偏移量
int __p_cnt;
int __p_int_key;
int __p_xty_key;
int __p_int_dat;
int __p_xty;
int __p_xty_dat;
int __z_xty_dat;
 
// 各数据段old偏移量
int __p_old ;
int __n_old;
int __p_cnt_old;
int __p_int_key_old;
int __p_xty_key_old;
int __p_int_dat_old;
int __p_xty_old;
int __p_xty_dat_old;
int __z_xty_dat_old;
int iCnt_old;
int xCnt_old;
 
int __p; // 内存起始地址
int __n; // 内存中的大小
}DatX;

参考文章:

1. 一种简易网络传输数据格式【替代json/xml】_类似json的数据格式-CSDN博客

2. 替代JSON-CSDN博客


原文地址:https://blog.csdn.net/shijianduan1/article/details/140687643

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!