2011-09-07 14 views
17

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

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

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

En caso afirmativo, cómo convertir todos estos bytes a un int equivalente.

+0

Según el origen de los datos, es posible que deba tener en cuenta la validez de los datos.Si los datos se crean y solo se transfieren en su código, entonces estaría bien, de lo contrario, debe tener en cuenta a little/big endian. – Joe

+0

posible duplicado de [Convertir NSdata a bytes y luego convertir los primeros n bytes a int] (http://stackoverflow.com/questions/7330436/converting-nsdata-to-bytes-then-converting-the-first-n- bytes-a-int) –

Respuesta

30

Es el valor 268566528 esperas o tal vez esperan que 528? Si el valor correcto es 528, entonces el orden de bytes es big-endian pero la CPU es little-endian, los bytes deben invertirse.

lo tanto, si el valor correcto debe ser 528 a continuación:

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

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

22

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

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

Para leer los datos desde el objeto a una NSData número entero que podría hacer algo como:

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

no es necesario para obtener los primeros 4 bytes si sólo están convirtiendo en un número entero. Puede hacerlo directamente desde las dos líneas anteriores y su receptor completeData

+0

Solución perfecta, de esta manera los datos serán LSB (listo para iOS) en un solo paso –

11

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

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

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

Datos de cuatro bytes <00000210> valor int: 268566528 obtengo la siguiente salida int para esta información. Es esto correcto ... solo me estoy preguntando. –

+0

@Pranav - Depende, ¿cuál es el orden de bytes de los datos en su instancia 'NSData'? – PeyloW

+0

Esto funciona perfectamente. – rjgonzo

5
- (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]; 
+0

La mejor solución hasta el momento –

4

iOS entero almacena LSB (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. marque 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; 
} 
+0

¡Impresionante! Especialmente si alguien está buscando una solución multiplataforma. –

1

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

Para hacerlo simple es necesario comprobar qué método de dos

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 comprobar cuál tiene más sentido al analizar los datos.