序列化数据传输压缩

1.名词解释

1.1序列化

序列化的数据传输时以一定格式传输

例:

struct data{
    int64 data1;
    int64 data2;
    char data3[25];
}

但传输的数据实际上data1和data2大部分数据都是非常小的,只有极少数的数据会用到64位数据来进行保存,这种时候本博客的传输压缩算法就有用武之地。

1.2 1248码:

在表示十进制数时计算机除了二进制编码之外还有一种编码方式叫做1248码,其用4位二进制数表示一位10进制数。使用的地方例如高考的答题卡的涂写中。

举个例子

十进制数255

对应的1248码的二进制的16进制表示就为:

0x0255

对应的机器二进制码的表示方法就为:

0xff

2.本算法的思路:

将大量的不需要用1248编码的数据放在序列化的数据的头地址,将需要1248码编码的数据放在后半部分。利用1248码所不能表示的10,11,12,13,14,15将数据分割,从而使数据变长去掉数据中大量不必要的0.

3.压缩算法:

虽然二进制的序列化的数据存储所需要的位数相对少一点,但是在序列化的时候,已经规定了数据所需的位数为64位。所以不论数据大小传输的时候都使用了64位来进行传输。大大的耗费了网络资源

压缩算法即先将数据转化为BCD编码后,在每一个数据的结尾利用1248码所不能表示的10,11,12,13,14,15来进行分割数据。

拿开始定义的data结构体来说事:

例如传输这么一个数据

data* a=(data*)malloc(sizeof(data));
data->data1=255;
data->data2=255;
data->data3="djwadja"

其所需传输的位数为64+64+25位。

而压缩算法传输的数据则为:

char[25]+0x255f255f

其传输的位数为25+64位。这样就可以大大减少0所占的位数。

4.使用此压缩算法的界线

对于64位的1248码所能表示的最大数为10^16,但因为其中有4位的分割符,所以所能表示的最大数为10^15

即当结构体中的某一个属性值有大量超过了10^15的数时,则此属性建议放入序列化中,不使用此压缩算法。

5.示例代码

经过测试,这个代码只适用于正整数,由于负数的补码下面代码不能压缩负数

#include<stdio.h>
#include<stdlib.h>
#define int64 long long
#define uchar unsigned char
typedef struct Stack_c{
	unsigned char data;
	struct Stack_c* next;
}Stack;

 typedef struct StackP_c{
	struct Stack_c* top;
	int len;
}StackP;

 typedef struct data_c{
	char data1[25];
	int64 data2;
}Data;

static StackP* stackTop;

void* codint64(int64 dataNode);

Stack* newSN(char nowData);

StackP* initStack();

void lpush(StackP* nowP,Stack* nowNode);

Stack* lpop(StackP* nowP);

void showAll(StackP* nowP);

void* codint(int dataNode);

char* putChar(StackP* nowP);

int main(){
	stackTop=initStack();	
	int64 a;
	int b;
	printf("input your num\n");
	scanf("%lld",&a);
	printf("input your num2\n");
	scanf("%d",&b);
	codint64(a);
	codint(b);
	printf("char arr is: ");
	putChar(stackTop);
	getchar();
	return 0;
}


void* codint64(int64 dataNode){
	char* nowData=(char*)(&dataNode);
	char sign=dataNode&0x80000000;
	char i=0x00;
	do{
		i=dataNode%10;
		i&=0x0f;
		Stack* nowNode=newSN(i);
		lpush(stackTop,nowNode);
		dataNode=dataNode/10;
	}while(dataNode>=1);
	if(sign==0x80000000){
		Stack* nowNode=newSN(0x0f);
		lpush(stackTop,nowNode);
	}else{
		Stack* nowNode=newSN(0x0e);
		lpush(stackTop,nowNode);
	}
	showAll(stackTop);
	return NULL;
}

Stack* newSN(char nowData){
	Stack* nowNode=(Stack*)malloc(sizeof(Stack));
	nowNode->next=NULL;
	nowNode->data=nowData;
	return nowNode;
} 

StackP* initStack(){
	 StackP* nowP=(StackP*)malloc(sizeof(StackP));
	 nowP->top=NULL;
	 nowP->len=0;
	 return nowP;
} 

void lpush(StackP* nowP,Stack* nowNode){
	if(nowP->top==NULL){
		nowP->top=nowNode;
		nowP->len=1;
	}
	else{
		nowNode->next=nowP->top;
		nowP->top=nowNode;
		nowP->len+=1;
	}
}

Stack* lpop(StackP* nowP){
	Stack* nowNode=nowP->top;
	nowP->top=nowNode->next;
	nowNode->next=NULL;
	return nowNode;
}

void showAll(StackP* nowP){
	if(nowP->top==NULL){
		printf("StackP is NULL\n");
		goto end;
	}
	Stack* nowNode=nowP->top;
	printf("%x",nowNode->data);
	do{
		nowNode=nowNode->next;
		printf("%x",nowNode->data);
	}while(nowNode->next!=NULL);
	printf("\n");
end:
	;
}

void* codint(int dataNode){
	char* nowData=(char*)(&dataNode);
	char sign=dataNode&0x80000000;
	char i=0x00;
	do{
		i=dataNode%10;
		i&=0x0f;
		Stack* nowNode=newSN(i);
		lpush(stackTop,nowNode);
		dataNode=dataNode/10;
	}while(dataNode>=1);
	if(sign==0x80000000){
		Stack* nowNode=newSN(0x0f);
		lpush(stackTop,nowNode);
	}else{
		Stack* nowNode=newSN(0x0e);
		lpush(stackTop,nowNode);
	}
	showAll(stackTop);
	return NULL;
}

char* putChar(StackP* nowP){
	uchar* backData=NULL;	
	Stack* nowNode1;
	Stack* nowNode2;
	unsigned char nowData1;
	unsigned char nowData2;
	int flag=0;
	int i=0;
	int len;
	if(nowP->len==0){
		return NULL;
	}
	else{
		if(nowP->len%2==0){
			len=(nowP->len)/2;
			backData=(char*)malloc(sizeof(char)*len);
		}
		else{
			len=(nowP->len/2)+1;
			backData=(char*)malloc(sizeof(char)*len);
		}
		memset(backData,0x00,len);
		do{
			if(flag==0){
				if(nowP->top==NULL){
					break;
				}
				nowNode1=lpop(nowP);
				nowData1=(nowNode1->data);
				flag=1;
				free(nowNode1);
			}
			else{
				if(nowP->top==NULL){
					nowData2=0x0f;
					nowData1=nowData1<<4;
					nowData2|=nowData1;
					*(backData+i)=nowData2;
					break;
				}
				nowNode2=lpop(nowP);
				nowData2=nowNode2->data;
				//nowData2=nowData1|nowData2;
				__asm {
					mov al, nowData1;
					shl al,4;
					mov nowData1, al;
				}
				__asm{
					mov al, nowData1;
					mov bl, nowData2;
					or al, bl;
					mov nowData2, al;
				}
				*(backData+i)=nowData2;
				free(nowNode2);
				flag=0;
				i++;
			}
			
		}while(nowP->top!=NULL);
		for(i=0;i<len;i++){
			printf("%x",*(backData+i));
		}
	}
	return backData;
}

请大家记住开源的目的是为了大家共同学习而不是为了占有而不是为了将别人的思维产品变为自己的所有之物,也不是为了将免费好吗!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值