(轉(zhuǎn))iOS基礎(chǔ)之字節(jié)處理(NSData,Byte,NSString轉(zhuǎn)換)

TCP傳輸協(xié)議:前2個(gè)子節(jié)為一個(gè)固定的字符,這里以0x809B為例,接著為4個(gè)子節(jié)(存放content的長(zhǎng)度),然后為傳輸?shù)膬?nèi)容content

TCP傳輸協(xié)議

以下內(nèi)容都在Demo中,有興趣可以下載

一、 拼接方式1---使用Byte數(shù)組

這里以傳輸一張圖片為例

1.1前期準(zhǔn)備---獲取一張圖片的大小
    NSString  *path=  [[NSBundle mainBundle] pathForResource:@"ceshi" ofType:@"jpeg"];
    NSData* content = [NSData dataWithContentsOfFile:path];
    int value = (int)content.length;

1.2 將長(zhǎng)度value轉(zhuǎn)換為4個(gè)字節(jié)
Byte byteData[4] = {};

byteData[0] =(Byte)((value & 0xFF000000)>>24);

byteData[1] =(Byte)((value & 0x00FF0000)>>16);

byteData[2] =(Byte)((value & 0x0000FF00)>>8);

byteData[3] =(Byte)((value & 0x000000FF));
//轉(zhuǎn)換為4個(gè)字節(jié)

1.3 拼接固定字符并轉(zhuǎn)為NSData
Byte byte[] = {0x80,0x9B,byteData[0],byteData[1],byteData[2],byteData[3]};
NSData *temphead = [[NSData alloc]initWithBytes:byte length:6];

1.4 拼接傳輸?shù)臄?shù)據(jù)(圖片)
//拼接content
NSMutableData *m_data = [[NSMutableData alloc] init];
[m_data appendData:temphead];
[m_data appendData:content];

二、 拼接方式2---使用十六進(jìn)制轉(zhuǎn)換

2.1前期準(zhǔn)備---獲取一張圖片的大小
    NSString  *path=  [[NSBundle mainBundle] pathForResource:@"ceshi" ofType:@"jpeg"];
    NSData* content = [NSData dataWithContentsOfFile:path];
    int value = (int)content.length;

2.2 將長(zhǎng)度value轉(zhuǎn)換十六進(jìn)制string
//將長(zhǎng)度轉(zhuǎn)為十進(jìn)制string
NSString* decimalString = [NSString stringWithFormat:@"%d",value];
//將十進(jìn)制string轉(zhuǎn)為十六進(jìn)制并保證長(zhǎng)度為8
NSString* firstHex = [decimalString decimalToHexWithLength:8];//私有方法(見(jiàn)Demo)

2.3 將十六進(jìn)拼接固定字符并轉(zhuǎn)為NSData
//將十六進(jìn)制拼接上809B
NSString* hexString = [NSString stringWithFormat:@"809B%@",firstHex];
//將十六進(jìn)制轉(zhuǎn)為NSData
NSData* temphead = [hexString convertBytesStringToData];

2.4 拼接傳輸?shù)臄?shù)據(jù)(圖片)
//拼接content
NSMutableData *m_data = [[NSMutableData alloc] init];
[m_data appendData:temphead];
[m_data appendData:content];

三、 解析數(shù)據(jù)

這里是模擬服務(wù)器返回的數(shù)據(jù)
因?yàn)榘l(fā)送給服務(wù)器內(nèi)容的格式根服務(wù)器返回的內(nèi)容的格式相同,所以這里我們直接解析我們發(fā)送給服務(wù)器的數(shù)據(jù)就可以

3.1 獲取頭部數(shù)據(jù)
NSData *head = [_receiveData subdataWithRange:NSMakeRange(0, 6)];//取得頭部數(shù)據(jù)
NSData *lengthData = [head subdataWithRange:NSMakeRange(2, 4)];//取得長(zhǎng)度數(shù)據(jù)

3.2 將4個(gè)字節(jié)的數(shù)據(jù)還原為content的長(zhǎng)度
1 將lengthData轉(zhuǎn)為16進(jìn)制數(shù)
NSString* hexString = [lengthData convertDataToHexStr];
2 將16進(jìn)制數(shù)轉(zhuǎn)為10進(jìn)制
NSInteger length = [[hexString hexToDecimal]integerValue];//得出content長(zhǎng)度

3.3 取出content的內(nèi)容
NSInteger complateDataLength = length + 6;//算出一個(gè)包完整的長(zhǎng)度(內(nèi)容長(zhǎng)度+頭長(zhǎng)度)
if (_receiveData.length >= complateDataLength)//如果緩存中數(shù)據(jù)夠一個(gè)整包的長(zhǎng)度
{
    //這個(gè)data即為我們傳出去的數(shù)據(jù)
    NSData *data = [_receiveData subdataWithRange:NSMakeRange(6, length)];//截取一個(gè)包的長(zhǎng)度(處理粘包)
    //顯示到程序上
    [self.resultImage setImage:[UIImage imageWithData:data]];
}

[圖片上傳失敗...(image-eb72c5-1534388160356)]

[圖片上傳失敗...(image-611834-1534388160356)]

四、 進(jìn)制、Byte、Byte數(shù)組、NSData的相互轉(zhuǎn)換(參考Demo)

#import "NSString+SwitchData.h"

@implementation NSString (SwitchData)
/**
 帶子節(jié)的string轉(zhuǎn)為NSData

 @return NSData類型
 */
-(NSData*) convertBytesStringToData {
    NSMutableData* data = [NSMutableData data];
    int idx;
    for (idx = 0; idx+2 <= self.length; idx+=2) {
        NSRange range = NSMakeRange(idx, 2);
        NSString* hexStr = [self substringWithRange:range];
        NSScanner* scanner = [NSScanner scannerWithString:hexStr];
        unsigned int intValue;
        [scanner scanHexInt:&intValue];
        [data appendBytes:&intValue length:1];
    }
    return data;
}
/**
 十進(jìn)制轉(zhuǎn)十六進(jìn)制

 @return 十六進(jìn)制字符串
 */
- (NSString *)decimalToHex {
    long long int tmpid = [self intValue];
    NSString *nLetterValue;
    NSString *str = @"";
    long long int ttmpig;
    for (int i = 0; i < 9; i++) {
        ttmpig = tmpid % 16;
        tmpid = tmpid / 16;
        switch (ttmpig) {
            case 10:
                nLetterValue = @"A";
                break;
            case 11:
                nLetterValue = @"B";
                break;
            case 12:
                nLetterValue = @"C";
                break;
            case 13:
                nLetterValue = @"D";
                break;
            case 14:
                nLetterValue = @"E";
                break;
            case 15:
                nLetterValue = @"F";
                break;
            default:
                nLetterValue = [[NSString alloc]initWithFormat:@"%lli", ttmpig];
        }
        str = [nLetterValue stringByAppendingString:str];
        if (tmpid == 0) {
            break;
        }
    }
    return str;
}
/**
 十進(jìn)制轉(zhuǎn)十六進(jìn)制
 length   總長(zhǎng)度,不足補(bǔ)0
 @return 十六進(jìn)制字符串
 */
- (NSString *)decimalToHexWithLength:(NSUInteger)length{
    NSString* subString = [self decimalToHex];
    NSUInteger moreL = length - subString.length;
    if (moreL>0) {
        for (int i = 0; i<moreL; i++) {
            subString = [NSString stringWithFormat:@"0%@",subString];
        }
    }
    return subString;
}
/**
 十六進(jìn)制轉(zhuǎn)十進(jìn)制

 @return 十進(jìn)制字符串
 */
- (NSString *)hexToDecimal {
    return [NSString stringWithFormat:@"%lu",strtoul([self UTF8String],0,16)];
}
/*
 二進(jìn)制轉(zhuǎn)十進(jìn)制

 @return 十進(jìn)制字符串
 */
- (NSString *)binaryToDecimal {
    int ll = 0 ;
    int  temp = 0 ;
    for (int i = 0; i < self.length; i ++) {
        temp = [[self substringWithRange:NSMakeRange(i, 1)] intValue];
        temp = temp * powf(2, self.length - i - 1);
        ll += temp;
    }
    NSString * result = [NSString stringWithFormat:@"%d",ll];
    return result;
}
/**
 十進(jìn)制轉(zhuǎn)二進(jìn)制

 @return 二進(jìn)制字符串
 */
- (NSString *)decimalToBinary {
    NSInteger num = [self integerValue];
    NSInteger remainder = 0;      //余數(shù)
    NSInteger divisor = 0;        //除數(shù)
    NSString * prepare = @"";

    while (true) {
        remainder = num%2;
        divisor = num/2;
        num = divisor;
        prepare = [prepare stringByAppendingFormat:@"%d",(int)remainder];

        if (divisor == 0) {
            break;
        }
    }

    NSString * result = @"";
    for (NSInteger i = prepare.length - 1; i >= 0; i --) {
        result = [result stringByAppendingFormat:@"%@",
                  [prepare substringWithRange:NSMakeRange(i , 1)]];
    }
    return [NSString stringWithFormat:@"%08d",[result intValue]];
}
@end

@implementation NSData (SwitchData)

/**
 NSData 轉(zhuǎn)  十六進(jìn)制string

 @return NSString類型的十六進(jìn)制string
 */
- (NSString *)convertDataToHexStr{
    if (!self || [self length] == 0) {
        return @"";
    }
    NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[self length]];

    [self enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
        unsigned char *dataBytes = (unsigned char*)bytes;
        for (NSInteger i = 0; i < byteRange.length; i++) {
            NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
            if ([hexStr length] == 2) {
                [string appendString:hexStr];
            } else {
                [string appendFormat:@"0%@", hexStr];
            }
        }
    }];

    return string;
}

/**
 NSData 轉(zhuǎn) NSString

 @return NSString類型的字符串
 */
- (NSString *)dataToString {
    Byte *bytes = (Byte *)[self bytes];
    NSMutableString *string = [[NSMutableString alloc] init];
    for(int i = 0; i< [self length]; i++) {
        if (i == 0) {
            [string appendString:[NSString stringWithFormat:@"%hhu",bytes[i]]];
        }else {
            [string appendString:[NSString stringWithFormat:@",%hhu",bytes[i]]];
        }
    }
    return string;
}
@end

寫在最后:
希望這篇文章對(duì)您有幫助。當(dāng)然如果您發(fā)現(xiàn)有可以優(yōu)化的地方,希望您能慷慨的提出來(lái)。最后祝您工作愉快!

作者:采釆一葉秋的iOS漫步
鏈接:http://www.itdecent.cn/p/cbdf76959406
來(lái)源:簡(jiǎn)書
簡(jiǎn)書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容