(转)iOS基础之字节处理(NSData,Byte,NSString转换)

TCP传输协议:前2个子节为一个固定的字符,这里以0x809B为例,接着为4个子节(存放content的长度),然后为传输的内容content

TCP传输协议

以下内容都在Demo中,有兴趣可以下载

一、 拼接方式1---使用Byte数组

这里以传输一张图片为例

1.1前期准备---获取一张图片的大小
    NSString  *path=  [[NSBundle mainBundle] pathForResource:@"ceshi" ofType:@"jpeg"];
    NSData* content = [NSData dataWithContentsOfFile:path];
    int value = (int)content.length;

1.2 将长度value转换为4个字节
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));
//转换为4个字节

1.3 拼接固定字符并转为NSData
Byte byte[] = {0x80,0x9B,byteData[0],byteData[1],byteData[2],byteData[3]};
NSData *temphead = [[NSData alloc]initWithBytes:byte length:6];

1.4 拼接传输的数据(图片)
//拼接content
NSMutableData *m_data = [[NSMutableData alloc] init];
[m_data appendData:temphead];
[m_data appendData:content];

二、 拼接方式2---使用十六进制转换

2.1前期准备---获取一张图片的大小
    NSString  *path=  [[NSBundle mainBundle] pathForResource:@"ceshi" ofType:@"jpeg"];
    NSData* content = [NSData dataWithContentsOfFile:path];
    int value = (int)content.length;

2.2 将长度value转换十六进制string
//将长度转为十进制string
NSString* decimalString = [NSString stringWithFormat:@"%d",value];
//将十进制string转为十六进制并保证长度为8
NSString* firstHex = [decimalString decimalToHexWithLength:8];//私有方法(见Demo)

2.3 将十六进拼接固定字符并转为NSData
//将十六进制拼接上809B
NSString* hexString = [NSString stringWithFormat:@"809B%@",firstHex];
//将十六进制转为NSData
NSData* temphead = [hexString convertBytesStringToData];

2.4 拼接传输的数据(图片)
//拼接content
NSMutableData *m_data = [[NSMutableData alloc] init];
[m_data appendData:temphead];
[m_data appendData:content];

三、 解析数据

这里是模拟服务器返回的数据
因为发送给服务器内容的格式根服务器返回的内容的格式相同,所以这里我们直接解析我们发送给服务器的数据就可以

3.1 获取头部数据
NSData *head = [_receiveData subdataWithRange:NSMakeRange(0, 6)];//取得头部数据
NSData *lengthData = [head subdataWithRange:NSMakeRange(2, 4)];//取得长度数据

3.2 将4个字节的数据还原为content的长度
1 将lengthData转为16进制数
NSString* hexString = [lengthData convertDataToHexStr];
2 将16进制数转为10进制
NSInteger length = [[hexString hexToDecimal]integerValue];//得出content长度

3.3 取出content的内容
NSInteger complateDataLength = length + 6;//算出一个包完整的长度(内容长度+头长度)
if (_receiveData.length >= complateDataLength)//如果缓存中数据够一个整包的长度
{
    //这个data即为我们传出去的数据
    NSData *data = [_receiveData subdataWithRange:NSMakeRange(6, length)];//截取一个包的长度(处理粘包)
    //显示到程序上
    [self.resultImage setImage:[UIImage imageWithData:data]];
}

[图片上传失败...(image-eb72c5-1534388160356)]

[图片上传失败...(image-611834-1534388160356)]

四、 进制、Byte、Byte数组、NSData的相互转换(参考Demo)

#import "NSString+SwitchData.h"

@implementation NSString (SwitchData)
/**
 带子节的string转为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;
}
/**
 十进制转十六进制

 @return 十六进制字符串
 */
- (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;
}
/**
 十进制转十六进制
 length   总长度,不足补0
 @return 十六进制字符串
 */
- (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;
}
/**
 十六进制转十进制

 @return 十进制字符串
 */
- (NSString *)hexToDecimal {
    return [NSString stringWithFormat:@"%lu",strtoul([self UTF8String],0,16)];
}
/*
 二进制转十进制

 @return 十进制字符串
 */
- (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;
}
/**
 十进制转二进制

 @return 二进制字符串
 */
- (NSString *)decimalToBinary {
    NSInteger num = [self integerValue];
    NSInteger remainder = 0;      //余数
    NSInteger divisor = 0;        //除数
    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 转  十六进制string

 @return NSString类型的十六进制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 转 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

写在最后:
希望这篇文章对您有帮助。当然如果您发现有可以优化的地方,希望您能慷慨的提出来。最后祝您工作愉快!

作者:采釆一叶秋的iOS漫步
链接:https://www.jianshu.com/p/cbdf76959406
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容