先上代碼
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長(zhǎng)度信息轉(zhuǎn)換成NSData二進(jìn)制數(shù)據(jù),這里的8表示生成一個(gè)8字節(jié)的容量,
&dataLength的&是取地址符。
有時(shí)候你還能見到這種寫法:
NSData *lengthData = [NSData dataWithBytes:&dataLength length:sizeof(dataLength)];
其實(shí)意思是一樣的,因?yàn)镹SInteger在iOS里占8個(gè)字節(jié)
接下來(lái):
NSData *newLengthData = [lengthData subdataWithRange:NSMakeRange(0, 4)];
這個(gè)意思是截取前4個(gè)字節(jié),為什么只接前4個(gè)字節(jié)?因?yàn)榇蟛糠智闆r下前4個(gè)字節(jié)就是完整的信息,后面4個(gè)字節(jié)全是0,試了將MAX_INT轉(zhuǎn)成data,前4個(gè)字節(jié)也完全可以存儲(chǔ)完整的信息。
最后:
NSInteger getDataLength1 = 0;
[lengthData getBytes:&getDataLength1 length:8];
將data轉(zhuǎn)成NSInteger獲取到data的實(shí)際長(zhǎng)度
使用場(chǎng)景一:socket通信粘包處理
當(dāng)讀取到數(shù)據(jù)寫入,先將數(shù)據(jù)加入到緩沖區(qū)
self.dataBuffer = [NSMutableData data];
[self.dataBuffer appendData:readData];
此處的readData為數(shù)據(jù)流讀出的某個(gè)完整數(shù)據(jù)的一部分,appendData:readData這個(gè)代碼可能執(zhí)行多次
截取前4個(gè)字節(jié)(這個(gè)字節(jié)數(shù)不一定要4個(gè)字節(jié) ,完全可以自己定義,跟服務(wù)器約定好就可以)
NSInteger dataLength = 0;
[self.dataBuffer getBytes:&getDataLength1 length:8];
if (self.dataBuffer.length >= dataLength+4) {
//取出我們想要的數(shù)據(jù)
NSData *completeData = [self.dataBuffer subdataWithRange:NSMakeRange(4, dataLength)];
//然后處理取出來(lái)的數(shù)據(jù)
//略.........
//移除已經(jīng)拆包的數(shù)據(jù)
[self.dataBuffer setData:[self.dataBuffer subdataWithRange:NSMakeRange(4+dataLength, self.dataBuffer.length - 4 - dataLength)]];
}