遍历字节数组以解析出各个长度

Posted

技术标签:

【中文标题】遍历字节数组以解析出各个长度【英文标题】:Iterate over byte array to parse out individual lengths 【发布时间】:2015-02-27 20:15:31 【问题描述】:

我正在通过核心蓝牙 (BLE) 从硬件设备读取数据。我正在阅读的特征之一是将结构压缩为单个值。编程到板上的结构如下所示:

typedef struct

  uint8          id;
  uint32        dur;
  uint16        dis;
 record;

我正在解析的大多数其他特征都是单一类型,uint8uint32,等等。

如何遍历字节并将每个单独的特征解析为原生类型或NSString?有没有办法遍历 NSData 对象的字节或子串?

NSData *data = [characteristic value]; // characteristic is of type CBCharacteristic
    NSUInteger len = data.length;
    Byte *bytes = (Byte *)[data bytes];
    for (Byte in bytes)  // no fast enumeration here, but the general intention is to iterate byte by byte
        // TODO: parse out uint8
        // TODO: parse out uint32
        // TODO: parse out uint16
    

【问题讨论】:

如果结构始终是固定布局,那么只需直接访问字节 - [data bytes][0] 将是您的 id。 [data bytes[1]]-[data bytes[4] will be dur and bytes 5 & 6 will be dis 【参考方案1】:

您可以执行这样的操作来从数据中创建结构的实例。

typedef struct

  uint8          id;
  uint32        dur;
  uint16        dis;
 record;

@implementation YourClass (DataRetrieval)
- (void)process:(CBCharacteristic *)characteristic 
  record r;
  [[characteristic value] getBytes:&r length:sizeof(r)];
  // r.id
  // r.dur
  // r.dis

@end

【讨论】:

结构存在于我正在连接的板子或设备上。它作为单个数据对象被推送到蓝牙上。该数据不会自动解析为 NSObject 或结构,映射必须手动完成,这就是我尝试迭代数据对象的原因。 如果你打算解析它,你必须知道你得到的数据的格式,对吧?只需在代码中定义一个与该格式匹配的结构。 也许他缺少的知识是他在示例中使用的结构将在 Objective-C 中按原样工作。 @ilrugel 答案有点不清楚,但在 Objective-C 中,您也可以使用 C 结构。只需在 ios 应用程序的代码中定义相同的结构 record 并像在 dan 的回答中一样使用它:在 NSData 的实例上调用 getBytes:length 后,record 结构中的所有字段都将被分配正确的值.【参考方案2】:

而不是遍历您的数据,如果您想提取单个值,您可以使用 Characteristic NSData 的 subDataWithRange。

类似...

    //create test data as an example.
    unsigned char bytes[STRUCT_SIZE] = 0x01, 0x00, 0x0, 0x00, 0x02, 0x00, 0x03;
    NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)];

    //assume that you have a packed structure and endianess is correct
    //[0] = id
    //[1] = dur
    //[2] = dur
    //[3] = dur
    //[4] = dur
    //[5] = dis
    //[6] = dis

    assert(STRUCT_SIZE == [data length]);

    uint8_t     idu = *( uint8_t*)[[data subdataWithRange:NSMakeRange(0, 1)] bytes];
    uint32_t    dur = *(uint32_t*)[[data subdataWithRange:NSMakeRange(1, 4)] bytes];
    uint16_t    dis = *(uint16_t*)[[data subdataWithRange:NSMakeRange(5, 2)] bytes];

    assert(1 == idu);
    assert(2 == dur);
    assert(3 == dis);

approach is here的一个很好的描述

还有endianness is here的方法

我也不确定你是不是doing any Structure Packing

【讨论】:

以上是关于遍历字节数组以解析出各个长度的主要内容,如果未能解决你的问题,请参考以下文章

C语言,结构体问题?所占内在字节数,怎么算的???

图中是把二十个字节的数组分成正数组和负数组,并分别计算两个数组中数据的个数的汇编程序。请画出程序流

使用 LINQ 在字节数组中搜索以特定字节开始/停止的所有子数组

java,要实现字符串按字节截取的方法

java,要实现字符串按字节截取的方法

大字节数组 - 在字节数组中存储长度有啥好处?