iOS之NSData和字节学习

NSData:

Nsdata里面可以放很多类型,可以放string类型,可以放十六进制数据,可以放十进制数据,可以放二进制数据等等等。

在oc中,主要与十进制数据打交道。在网络传输中,我们可以讲十进制数据封装在nsdata中传输,也可以讲字符串封在nsdata中传输。但是有些单芯片设备,比如蓝牙传输,无法讲字符串封装在nsdata中传输。这时候我们就只能用最底层的数据传输了。二进制,八进制,十进制,十六进制。

假设,我们用十进制传输:我们可以把传输的十进制的每个数字分别代表什么拟定出来,然后双方根据这个规则去做事情,这就是协议。我们知道十进制0-255之间的数字都占1个字节。那么我可以:int a = 27;协议里面定好27代表开锁的意思。那么int转为nsdata 然后传输nsdata到锁里面,锁里面根据协议 解析出来十进制,发现是27就会进行开锁操作。

假设,我们用十六进制传输:我们把传输的每一个十六进制的数字代表什么意思拟定协议。我们又知道,十六进制是两位占一个字节(二进制是八位占一个字节:8个二进制位构成1个字节),比如0x01。0x表示16进制,十六进制的01其实就是十进制的数字1。01代表开锁,那么我们可以用两种方式去把01封装到nsdata里面。

第一种:采用c语言btye,因为在oc中,我们有表示十进制数字的int long等类型来赋值十进制数字,像int一样赋值之后转换为nsdata就可以了。但是却没有表示十六进制的类型来赋值数组封装成nsdata。要想直接用十六进制赋值然后转换成nsdata,就只能用c语言的btye数组来做。btye数组可以不进直接放十六进制,也可以放二进制,十进制数据类型。

第二种:采用十六进制字符串形式封装(原理其实还是byte),此方法如下:因为你无法直接在oc中找到赋值十六进制的类型,所以你可以将十六进制的数据直接用字符串方式写出来,赋值给字符串,然后用这个方法帮你写到nsdata中,并且会是以十六进制类型写入。


#pragma mark 16进制字符串转换为data类型
+ (NSMutableData *)convertHexStrToData:(NSString *)str {
    if (!str || [str length] == 0) {
        return nil;
    }
    
    NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
    NSRange range;
    if ([str length] %2 == 0) {
        range = NSMakeRange(0,2);
    } else {
        range = NSMakeRange(0,1);
    }
    for (NSInteger i = range.location; i < [str length]; i += 2) {
        unsigned int anInt;
        NSString *hexCharStr = [str substringWithRange:range];
        NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
        
        [scanner scanHexInt:&anInt];
        NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
        [hexData appendData:entity];
        
        range.location += range.length;
        range.length = 2;
    }
    
    return hexData;
}

为什么要用十六进制数据?

由于数据在计算机中的表示,最终以二进制的形式存在,所以有时候使用二进制,可以更直观地解决问题。但,二进制数太长了。比如int 类型占用4个字节,32位。
比如100,用int类型的二进制数表达将是:0000 0000 0000 0000 0110 0100面对这么长的数进行思考或操作,没有人会喜欢。因此,C,C++ 没有提供在代码直接写二进制数的方法。用16进制或8进制可以解决这个问题。因为,进制越大,数的表达长度也就越短。

一个字节可以用多少位的十六进制表示?

一个字节=8位(bit)
二进制用字母B表示,十六进制用H表示。
十进制的数码:1到9和0
十六进制的数码有1,2,3,4,5,6,7,8,9,A(10),B(11),C(12),D(13),E(14),F(15)
二进制只有0和1两个数,最大的八位二进制数就是8个1,即11111111。
所以:
11111111 B(二进制)
=255 D(十进制):个十百~3位
=FF H(十六进制):个十~2位

1,一个字节包含8个二进制位
2,一个十六进制可表示4个二进制位
3,所以,一个字节可以由2个十六进制表示

iOS如何定义byte数组,写入读取?

使用的是C语言里面的编写方式:其中byte可以用char效果也是一样的,(type 'Byte *' (aka 'unsigned char *'))
byte:unit8,无符号8bit整数,相当于char
oc中:
typedef unsigned char UInt8;
typedef UInt8 Byte;

char vs unsigned char
相同点:在内存中都是一个字节,8位(2^8=256),都能表示256个数字
不同点:char的最高位为符号位,因此char能表示的数据范围是-128~127,unsigned char没有符号位,因此能表示的数据范围是0~255

byte数组:里面一般存放字节.在十六进制使用的时候会用到
1、定义: 100表示长度,设置为0,可以控制不出现乱码
Byte data[100] = {0};//意思是data里面有100个字节,因为c中byte和java中不一样,btye定义就是char类型,8位一个字节类型,所以data[0]中只能放一个字节,不能放多个字节。
data[0] = 0x00;
data[1] = 0x55;
data[2] = 0x05;

也可以这么写:Byte byte[] = {0x00,0x55,0x05};
2、通过NSData把Byte所有内容取出来,进行读取
NSData *data1 = [NSData dataWithBytes:data length:CmdDataSetSize];//CmdDataSetSize是有效字节长度,意思是data中有100个字节,比如我们需要其中的前50个,那么这个CmdDataSetSize就是50,转后的data1的长度也是50
NSLog(@"测试%@",data1);
3、对某一个字节进行设置.
data[5] = 0x66;
NSLog(@"测试data%@",data);

nsdata和byte数组转换?

Byte *testByte = (Byte *)[data bytes];

NSData *data = [NSData dataWithBytes:testByte length:sizeof(testByte)];
//sizeof()是c语言的一个函数,返回testbyte的字节长度
//testByte也可以是char类型,因为:
typedef unsigned char UInt8;
typedef UInt8 Byte;

Demo地址

你可能感兴趣的:(iOS之NSData和字节学习)