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.
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.
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
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]);
- (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];
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;
}
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.
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