objective framework apple iphone objective-c ipad nsdata

iphone - framework - Convertir NSData a int



objective c documentation (7)

Tengo un objeto NSData, la longitud es de 4 bytes. Estos cuatro bytes que estoy extrayendo de otro objeto NSData usando,

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

Mi primera pregunta es si la declaración anterior me proporcionará los primeros cuatro bytes de datos completos.

Si es Sí, entonces cómo convertir todos estos bytes a un int equivalente.


¿Es 268566528 el valor que espera o quizás espera 528? Si el valor correcto es 528, el orden de bytes es big-endian pero la cpu es little-endian, los bytes deben invertirse.

Entonces, si el valor correcto debería ser 528 entonces:

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

También tenga en cuenta que el orden estándar de la red es big-endian.


Depende de la notación de Endianness de los datos que desea convertir, en relación con la notación de Endianness de su dispositivo. wiki sobre endianness

Para que sea sencillo hay que comprobar dos métodos.

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

o

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

Y compruebe cuál tiene más sentido cuando analiza los datos.


El entero de iOS almacena LSB (el byte más bajo significativo) en el primer byte y MSB en el último byte. Tengo la rutina de conversión para probar todas esas cosas. Chequea aquí,

Prueba ...

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


Esa declaración le daría los primeros 16 bytes de datos, no 4. Para obtener los primeros 4 bytes, necesita modificar su declaración para:

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

Para leer los datos del objeto NSData a un entero, podría hacer algo como:

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

No necesita obtener los primeros 4 bytes si solo lo está convirtiendo en un entero. Puede hacerlo directamente desde las dos líneas anteriores y su receptor de datos completeData


No, obtendrá 16 bytes de datos, ya que el rango es de 0 y luego de 16 bytes.

Si tuviera una instancia de NSData con 4 bytes, entonces podría hacer un tipo de NSData simple como este:

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


Suponiendo que _vertexData es NSData aquí y usted sabe qué datos (tipos) esperar en su búfer puede iterar a través de este bloque con la propiedad .length de .length . En este ejemplo, cada bloque de datos tenía 32 bytes (almacenando 8 x valores flotantes ) y estaba interesado en el registro a partir del quinto valor flotante

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

Esto podría haber sido escrito mucho más corto, pero en aras de la claridad y con menos uso de piezas de fundición de primera clase.

tal vez esto ayude a alguien


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