开发者

Converting NSData to int

I've an NSData object, the length is 4 bytes .These four bytes i'm extracting from another NSData object using ,

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

My first question is, will the above statement provide me the first 开发者_JAVA技巧four bytes of complete data.

If Yes, then how to convert all these bytes to an equivalent int.


Is 268566528 the value you expect or perhaps you expect 528? If the correct value is 528 then the byte order is big-endian but the cpu is little-endian, the bytes need to be reversed.

So, if the correct value should be 528 then:

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

Also note that network standard order is big-endian.


That statement would give you the first 16 bytes of data, not 4. To get the first 4 bytes you need to modify your statement to:

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

To read the data from the NSData Object to an integer you could do something like:

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

You do not need to get the first 4 bytes if you are just converting it to an integer. You can do this directly from the two lines above and your completeData receiver


No you will get 16 bytes of data, since the range is from offset 0 and then 16 bytes.

If you had a NSData instance with 4 bytes then you could do a simple type cast like this:

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


- (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];


iOS integer stores LSB (lowest significant byte) in the first byte and MSB in the last byte. I have conversion routine to test all those things. check here,

Test ...

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;
}


It depends on the Endianness notation of the data you want to convert, in relation to your device Endianness notation. wiki on Endianness

To keep it simple you need to check does two method

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

or

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

And check which one make more sense when you parse the data.


Assuming _vertexData is NSData here and you know what data (types) to expect in your buffer you can iterate thru this block with NSData's .length property. In this Example each data block was 32 Bytes (storing 8 x float values) and i was interested in logging starting at the 5th float value

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 );
}

this could have been written much shorter, but for the sake of clarity and with less use of miss leading castings

maybe this helps someone

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜