【问题标题】:Converting NSData to int将 NSData 转换为 int
【发布时间】:2011-09-07 10:53:12
【问题描述】:

我有一个 NSData 对象,长度为 4 个字节。这四个字节是我从另一个 NSData 对象中提取的,

fourByteData=[completeData subdataWithRange:NSMakeRange(0, 16)];

我的第一个问题是,上面的语句是否会提供我完整数据的前四个字节。

如果是,那么如何将所有这些字节转换为等效的 int。

【问题讨论】:

标签: iphone objective-c ipad nsdata


【解决方案1】:

268566528 是您期望的值还是您期望的 528?如果正确的值是528那么字节顺序是big-endian但cpu是little-endian,字节需要颠倒。

所以,如果正确的值应该是 528 那么:

NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
int value = CFSwapInt32BigToHost(*(int*)([data4 bytes]));

还要注意网络标准顺序是大端的。

【讨论】:

    【解决方案2】:

    不,您将获得 16 字节的数据,因为范围是从偏移量 0 到 16 字节。

    如果您有一个 4 字节的 NSData 实例,那么您可以像这样进行简单的类型转换:

    int value = *(int*)([data bytes]);
    

    【讨论】:

    • 四字节数据 int value: 268566528 我得到了这个数据的以下 int 输出。这是对的........只是想知道。
    • @Pranav - 视情况而定,NSData 实例中数据的字节顺序是什么?
    【解决方案3】:

    该语句将为您提供前 16 个字节的数据,而不是 4 个。要获取前 4 个字节,您需要将语句修改为:

    fourByteData = [completeData subdataWithRange:NSMakeRange(0, 4)];
    

    要将数据从 NSData 对象读取为整数,您可以执行以下操作:

    int theInteger;
    [completeData getBytes:&theInteger length:sizeof(theInteger)];
    

    如果您只是将其转换为整数,则不需要获取前 4 个字节。您可以直接从上面的两行和您的completeData 接收者执行此操作

    【讨论】:

    • 完美的解决方案,这样一来数据就可以一步完成LSB(iOS ready)
    【解决方案4】:
    - (unsigned)parseIntFromData:(NSData *)data{
    
        NSString *dataDescription = [data description];
        NSString *dataAsString = [dataDescription substringWithRange:NSMakeRange(1, [dataDescription length]-2)];
    
        unsigned intData = 0;
        NSScanner *scanner = [NSScanner scannerWithString:dataAsString];
        [scanner scanHexInt:&intData];
    
        return intData;
    }
    
    int numberOfChunks = [self parseIntFromData:data];
    

    【讨论】:

    • 迄今为止最好的解决方案
    【解决方案5】:

    iOS 整数在第一个字节中存储 LSB(最低有效字节),在最后一个字节中存储 MSB。我有转换程序来测试所有这些东西。看这里,

    测试...

    int i = 2342342;
        NSData * d1 = [Util dataFromInt:i]; // {[MSB], ..., ... ,[LSB]} <0023bdc6>
        NSData * d2 = [NSData dataWithBytes:&i length:4];  // {[LSB], ..., ... ,[MSB]} <c6bd2300>
        int ci1 = [Util intFromData:d1];
        int ci2 = [Util intFromDataReverse:d2];
    

    Util.m

    + (NSData *) dataFromInt:(int)num {
        unsigned char * arr = (unsigned char *) malloc(sizeof(num) * sizeof(unsigned char));
        for (int i = sizeof(num) - 1 ; i >= 0; i --) {
            arr[i] = num & 0xFF;
            num = num >> 8;
        }
        NSData * data = [NSData dataWithBytes:arr length:sizeof(num)];
        free(arr);
        return data;
    }
    
    // {[MSB], ..., ... ,[LSB]}
    + (int) intFromData:(NSData *)data
    {
        int intSize = sizeof(int); // change it to fixe length
        unsigned char * buffer = malloc(intSize * sizeof(unsigned char));
        [data getBytes:buffer length:intSize];
        int num = 0;
        for (int i = 0; i < intSize; i++) {
            num = (num << 8) + buffer[i];
        }
        free(buffer);
        return num;
    }
    
    // {[LSB], ..., ... ,[MSB]}
    + (int) intFromDataReverse:(NSData *)data
    {
        int intSize = sizeof(int);// change it to fixe length
        unsigned char * buffer = malloc(intSize * sizeof(unsigned char));
        [data getBytes:buffer length:intSize];
        int num = 0;
        for (int i = intSize - 1; i >= 0; i--) {
            num = (num << 8) + buffer[i];
        }
        free(buffer);
        return num;
    }
    

    【讨论】:

    • 太棒了!特别是如果有人正在寻找跨平台解决方案。
    【解决方案6】:

    这取决于您要转换的数据的字节序表示法,与您的设备字节序表示法有关。 wiki on Endianness

    为了简单起见,您需要检查两种方法

    NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
    int value = CFSwapInt32BigToHost(*(int*)([data4 bytes]));
    

    NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
    int value = CFSwapInt32LittleToHost(*(int*)([data4 bytes]));
    

    并在解析数据时检查哪一个更有意义。

    【讨论】:

      【解决方案7】:

      这里假设 _vertexDataNSData 并且您知道缓冲区中期望的数据(类型),您可以使用 NSData 的 .length 属性遍历此块。 在此示例中,每个数据块为 32 字节(存储 8 x 浮点 值),我对从 第 5 个浮点值开始记录感兴趣

      float a,b,c,d; //prepare some values, no need to initialize
      
      // loop thru assuming 8 floats are stored after each other
      for (NSUInteger v = 0; v < _vertexData.length; v += sizeof(float)*8 ) {
      
          // set a starting point for the range, here the 5th float
          NSUInteger shift = v + (sizeof(float)*4);
      
          // store result in a..
          [_vertexData getBytes:&a range:NSMakeRange(shift,sizeof(a))];
      
          // increase the starting point by the size of data before
          shift += sizeof(a);
      
          [_vertexData getBytes:&b range:NSMakeRange(shift,sizeof(b))];
      
          shift += sizeof(b);
          [_vertexData getBytes:&c range:NSMakeRange(shift,sizeof(c))];
      
          shift += sizeof(c);
          [_vertexData getBytes:&d range:NSMakeRange(shift,sizeof(d))];
      
          fprintf(stderr, "r%f, g%f, b%f, a%f \n", a,b,c,d );
      }
      

      这本可以写得更短,但为了清楚起见并减少使用未命中的铸件

      也许这对某人有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-28
        • 2016-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多