Converting NSData to int

2020-02-02 11:07发布

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 four bytes of complete data.

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

7条回答
Animai°情兽
2楼-- · 2020-02-02 11:45

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;
}
查看更多
闹够了就滚
3楼-- · 2020-02-02 11:45

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.

查看更多
女痞
4楼-- · 2020-02-02 11:45

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

查看更多
Explosion°爆炸
5楼-- · 2020-02-02 11:47
- (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];
查看更多
叛逆
6楼-- · 2020-02-02 12:01

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

查看更多
相关推荐>>
7楼-- · 2020-02-02 12:04

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]);
查看更多
登录 后发表回答