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

漫步

TCP傳輸協(xié)議:前2個子節(jié)為一個固定的字符夺英,這里以0x809B為例痛悯,接著為4個子節(jié)(存放content的長度)载萌,然后為傳輸?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 將長度value轉(zhuǎn)換為4個字節(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個字節(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 將長度value轉(zhuǎn)換十六進(jìn)制string
//將長度轉(zhuǎn)為十進(jìn)制string
NSString* decimalString = [NSString stringWithFormat:@"%d",value];
//將十進(jìn)制string轉(zhuǎn)為十六進(jìn)制并保證長度為8
NSString* firstHex = [decimalString decimalToHexWithLength:8];//私有方法(見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)];//取得長度數(shù)據(jù)
3.2 將4個字節(jié)的數(shù)據(jù)還原為content的長度
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長度
3.3 取出content的內(nèi)容
NSInteger complateDataLength = length + 6;//算出一個包完整的長度(內(nèi)容長度+頭長度)
if (_receiveData.length >= complateDataLength)//如果緩存中數(shù)據(jù)夠一個整包的長度
{
    //這個data即為我們傳出去的數(shù)據(jù)
    NSData *data = [_receiveData subdataWithRange:NSMakeRange(6, length)];//截取一個包的長度(處理粘包)
    //顯示到程序上
    [self.resultImage setImage:[UIImage imageWithData:data]];
}
image.png
image.png

四、 進(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   總長度,不足補(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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胯陋,一起剝皮案震驚了整個濱河市袱箱,隨后出現(xiàn)的幾起案子发笔,更是在濱河造成了極大的恐慌凉翻,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件量蕊,死亡現(xiàn)場離奇詭異残炮,居然都是意外死亡势就,警方通過查閱死者的電腦和手機(jī)脉漏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門侧巨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人皇忿,你說我怎么就攤上這事坦仍。” “怎么了幔荒?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵爹梁,是天一觀的道長卫键。 經(jīng)常有香客問我虱朵,道長,這世上最難降的妖魔是什么絮宁? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任绍昂,我火速辦了婚禮偿荷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忍饰。我一直安慰自己寺庄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布您旁。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贞岭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天宪彩,我揣著相機(jī)與錄音尿孔,去河邊找鬼筹麸。 笑死,一個胖子當(dāng)著我的面吹牛白指,可吹牛的內(nèi)容都是我干的酵紫。 我是一名探鬼主播错维,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼赋焕,長吁一口氣:“原來是場噩夢啊……” “哼隆判!你這毒婦竟也來了僧界?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤咬腕,失蹤者是張志新(化名)和其女友劉穎郎汪,沒想到半個月后闯狱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哄孤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凝危。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡蛾默,死狀恐怖捉貌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情趁窃,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布瀑构,位于F島的核電站刨摩,受9級特大地震影響世吨,放射性物質(zhì)發(fā)生泄漏折剃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一怕犁、第九天 我趴在偏房一處隱蔽的房頂上張望奏甫。 院中可真熱鬧凌受,春花似錦、人聲如沸挠进。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至君旦,卻和暖如春嘲碱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恕稠。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工扶欣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人昆著。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓凑懂,卻偏偏與公主長得像梧宫,于是被迫代替她去往敵國和親摆碉。 傳聞我的和親對象是個殘疾皇子脓豪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容