大小端数据存储
概念:
大端模式:是指数据的高字节保存在内存的低地址中,而低子节数据保存在内存的高地址中。
小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。
新的需求:
这是移动端日志数据传给服务器的格式:
{“flag”:16,“item”:{“group”:“xxxxxx”,“mirror”:1,“items”:[{“flag”:1,“key”:“log”,“datas”:[“data:application/octet-stream;base64,xxxxxxx”]}]}}
[total_len(4b)][format(4b)][type_len(1b)][type_padding_len(1b)][data_padding_len(1b)] [reserved(1b)][type][data]。
format为格式,固定长度,为4个字节。type_len一种type的实际长度。Type_padding_len为type补位个数。data_padding _len为data补位个数。total_len为整个数据的长度,占4个字节,大端字节序存储。type为存储数据类型,data为存储数据,都建议4字节对齐,末位补/0。
疑惑:
之前不知道大小端数据是咋回事,一头雾水。问了安卓同事才勉强明白,我们先了解下Byte,Object-C里面其实是沿用C++的,下面是Byte的定义:
*********************************************************************************/
//Byte是UInt8的别名
typedef UInt8 Byte;
typedef SInt8 SignedByte;
typedef wide * WidePtr;
typedef UnsignedWide * UnsignedWidePtr;
typedef Float80 extended80;
typedef Float96 extended96;
typedef SInt8 VHSelect;
/*********************************************************************************
/********************************************************************************
Base integer types for all target OS's and CPU's
UInt8 8-bit unsigned integer
SInt8 8-bit signed integer
UInt16 16-bit unsigned integer
SInt16 16-bit signed integer
UInt32 32-bit unsigned integer
SInt32 32-bit signed integer
UInt64 64-bit unsigned integer
SInt64 64-bit signed integer
*********************************************************************************/
//UInt8是unsigned char 别名
typedef unsigned char UInt8;
typedef signed char SInt8;
typedef unsigned short UInt16;
typedef signed short SInt16;
#if __LP64__
typedef unsigned int UInt32;
typedef signed int SInt32;
#else
typedef unsigned long UInt32;
typedef signed long SInt32;
#endif
下面是iOS的实现:
- (NSString *)logByteFill:(NSString *)data format:(NSString *)format type:(NSString *)type {
if (data == NULL) {
return @"";
}
int type_padding_len = 0;
int type_len = (int)type.length;//type的实际长度,都是英文,一个英文单词一个字节
int temp = 4 - type_len % 4;
if (temp != 4) {
type_padding_len = temp;
}
//JSON字符串的字节长度
int data_len = (int)[data lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
int data_padding_len = 4 - data_len % 4;
if (data_padding_len != 4) {
data_len = data_len + data_padding_len;
} else {
data_padding_len = 0;
}
int total_len = 12 + type_len + data_len;
if (type_padding_len != 4) {
total_len = 12 + type_len + type_padding_len + data_len;
}
NSMutableString *mutable_cmd = [[NSMutableString alloc] initWithString:type];
for (int i = 0; i < type_padding_len; i++) {
[mutable_cmd appendString:@"0"];
}
NSMutableString *mutable_data = [[NSMutableString alloc] initWithString:data];
for (int i = 0; i < data_padding_len; i++) {
[mutable_data appendString:@"0"];
}
Byte finalArray[12];
//total段
Byte total_byte[4] = {0};
Byte *total_ptr = total_byte;
//int 转 byte数组
*(int*)total_ptr = total_len;
finalArray[0] = total_byte[0];
finalArray[1] = total_byte[1];
finalArray[2] = total_byte[2];
finalArray[3] = total_byte[3];
//format段,固定“json”格式
Byte format_byte[4];
Byte *format_ptr = format_byte;
//int 转 byte数组
int format_len = (int)format.length;
*(int*)format_ptr = format_len;
finalArray[4] = format_byte[0];
finalArray[5] = format_byte[1];
finalArray[6] = format_byte[2];
finalArray[7] = format_byte[3];
//type段,占一个字节
Byte type_byte[1];
Byte *type_ptr = type_byte;
//int 转 byte数组
*(int*)type_ptr = type_len;
finalArray[8] = type_byte[0];
//type_padding段,占一个字节
Byte type_padding_byte[1];
Byte *type_padding_ptr = type_padding_byte;
//int 转 byte数组
*(int*)type_padding_ptr = type_padding_len;
finalArray[9] = type_padding_byte[0];
//type_padding段,占一个字节
Byte data_padding_byte[1];
Byte *data_padding_ptr = data_padding_byte;
//int 转 byte数组
*(int*)data_padding_ptr = data_padding_len;
finalArray[10] = data_padding_byte[0];
//reased Byte段,占一个字节
finalArray[11] = 0x00; //strtoul("0x00",0,16);
//固定12个字节data
NSData *fiex_data = [[NSData alloc] initWithBytes:&finalArray length:12];
//type数据段
NSData *type_data = [mutable_cmd dataUsingEncoding:NSUTF8StringEncoding];
//data数据段
NSData *data_data = [mutable_data dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *all_data = [[NSMutableData alloc] init];
[all_data appendData:fiex_data];
[all_data appendData:type_data];
[all_data appendData:data_data];
NSData *base64Data = [all_data base64EncodedDataWithOptions:0];
NSString *baseString = [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];
NSString *base64 = [NSString stringWithFormat:@"data:application/octet-stream;base64,%@",baseString];
return base64;
}
那个Byte数组那里的代码有点重复,我想抽一下,因为Object-C Byte类型不能作为函数值,所以就这样了。int转Byte数组有种C++方式:
测试:
//json 33 + cmd + 10 +补位json(3)+cmd(2)+固定长度12=60
NSString *json = @"{\"fileName\":\"log.ios.frfr4.h264\"}";
NSString *format = @"json";
NSString *cmd = @"openStream";
NSString *data = [self logByteFill:json format:format type:cmd];
NSLog(@"最后DATA == %@",data);