先上代码
NSString *str = @"i'm a test string";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSInteger dataLength = data.length;
NSData *lengthData = [NSData dataWithBytes:&dataLength length:8];
NSData *newLengthData = [lengthData subdataWithRange:NSMakeRange(0, 4)];
NSInteger getDataLength = 0;
[newLengthData getBytes:&getDataLength length:sizeof(getDataLength)];
NSInteger getDataLength1 = 0;
[lengthData getBytes:&getDataLength1 length:8];
这里解释一下代码:
NSData *lengthData = [NSData dataWithBytes:&dataLength length:8];
整行代码表示将dataLength长度信息转换成NSData二进制数据,这里的8
表示生成一个8字节的容量,
&dataLength
的&
是取地址符。
有时候你还能见到这种写法:
NSData *lengthData = [NSData dataWithBytes:&dataLength length:sizeof(dataLength)];
其实意思是一样的,因为NSInteger在iOS里占8个字节
接下来:
NSData *newLengthData = [lengthData subdataWithRange:NSMakeRange(0, 4)];
这个意思是截取前4个字节,为什么只接前4个字节?因为大部分情况下前4个字节就是完整的信息,后面4个字节全是0,试了将MAX_INT转成data,前4个字节也完全可以存储完整的信息。
最后:
NSInteger getDataLength1 = 0;
[lengthData getBytes:&getDataLength1 length:8];
将data转成NSInteger获取到data的实际长度
使用场景一:socket通信粘包处理
当读取到数据写入,先将数据加入到缓冲区
self.dataBuffer = [NSMutableData data];
[self.dataBuffer appendData:readData];
此处的readData
为数据流读出的某个完整数据的一部分,appendData:readData
这个代码可能执行多次
截取前4个字节(这个字节数不一定要4个字节 ,完全可以自己定义,跟服务器约定好就可以)
NSInteger dataLength = 0;
[self.dataBuffer getBytes:&getDataLength1 length:8];
if (self.dataBuffer.length >= dataLength+4) {
//取出我们想要的数据
NSData *completeData = [self.dataBuffer subdataWithRange:NSMakeRange(4, dataLength)];
//然后处理取出来的数据
//略.........
//移除已经拆包的数据
[self.dataBuffer setData:[self.dataBuffer subdataWithRange:NSMakeRange(4+dataLength, self.dataBuffer.length - 4 - dataLength)]];
}