web-dev-qa-db-fra.com

Conversion de NSData en int

J'ai un objet NSData, la longueur est de 4 octets. Ces quatre octets sont extraits d'un autre objet NSData à l'aide de,

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

Ma première question est de savoir si la déclaration ci-dessus me fournira les quatre premiers octets de données complètes.

Si oui, alors comment convertir tous ces octets en un équivalent int.

19
Pranav Jaiswal

268566528 est la valeur que vous attendez ou peut-être que vous attendez 528? Si la valeur correcte est 528, alors l'ordre des octets est big-endian mais le cpu est little-endian, les octets doivent être inversés.

Donc, si la valeur correcte doit être 528, alors:

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

Notez également que la commande standard du réseau est big-endian.

32
zaph

Cette instruction vous donnerait les 16 premiers octets de données, et non 4. Pour obtenir les 4 premiers octets, vous devez modifier votre instruction en:

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

Pour lire les données de l'objet NSData en un entier, vous pouvez effectuer les opérations suivantes:

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

Vous n'avez pas besoin d'obtenir les 4 premiers octets si vous le convertissez simplement en un entier. Vous pouvez le faire directement à partir des deux lignes ci-dessus et de votre récepteur completeData

25
Suhail Patel

Non, vous obtiendrez 16 octets de données, car la plage va de l'offset 0 à 16 octets.

Si vous avez une instance NSData avec 4 octets, vous pouvez faire un transtypage simple comme ceci:

int value = *(int*)([data bytes]);
12
PeyloW
- (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
Rubycon

le nombre entier iOS stocke LSB (octet significatif le plus faible) dans le premier octet et MSB dans le dernier octet. J'ai une routine de conversion pour tester toutes ces choses. vérifier ici,

Testez ... 

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

Cela dépend de la notation Endianness des données que vous voulez convertir, en relation avec la notation de votre appareil. wiki on Endianness

Pour rester simple, vous devez vérifier deux méthodes

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

ou

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

Et vérifiez laquelle est plus logique lorsque vous analysez les données.

1
TtheTank

En supposant que _vertexData est NSData ici Et que vous savez quels types de données (types) attendre dans votre tampon, vous pouvez parcourir ce bloc avec la propriété .length de NSData. Dans cet exemple, chaque bloc de données était 32 octets (stockage 8 x float valeurs) et j’étais intéressé par la journalisation à partir de la 5ème valeur float

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

cela aurait pu être écrit beaucoup plus court, mais par souci de clarté et en utilisant moins de casse-têtes

peut-être que cela aide quelqu'un

0
Ol Sen