2009-09-11 12 views
6

Obtengo un archivo html como NSData y necesito analizarlo para extraer algo de información. Mi enfoque era convertirlo a NSString con codificación UTF8 (el html no tiene caracteres en inglés, ruso por ejemplo) - falló. Utilicé algo así:NSData al problema de conversión de NSString!

NSString *respData = [NSString stringWithUTF8String:[theData bytes]]; 

pero devolvió nil.

La única cosa que funcionaba era

[NSString stringWithCString:[theData bytes] length:[theData length]]; 

pero cuando se encuentra con caracteres rusos, por ejemplo, se devuelve jibrish.

Luego mi siguiente enfoque fue analizar el conjunto de bytes de los datos, extraer los bytes que necesito y convertirlos de alguna manera a NSString. He intentado algo así:

-(NSString *)UTF8StringFromData:(NSData *)theData{ 
Byte *arr = [theData bytes]; 
NSUInteger begin1 = [self findIndexOf:@"<li>" bArr:arr size:[theData length]]+4; 
NSUInteger end1 = [self findIndexOf:@"</li></ol>" bArr:arr size:[theData length]]; 
Byte *arr1 = (Byte *)malloc(sizeof(Byte)*((end1-begin1+1))); 
int j = 0; 
for (int i = begin1; i < end1; i++){ 
    arr1[j] = arr[i]; 
    j++; 
} 
arr1[j]='\0'; 
NSData *temp = [NSData dataWithBytes:arr1 length:j]; 
return [[NSString alloc] initWithData:temp encoding:NSUTF8StringEncoding]; 
} 
+1

¿Estás seguro de * * que el archivo está codificado como UTF-8, y no como la norma ISO 8859-5 o algo? – Wevah

Respuesta

0

En primer lugar aquí es mi código

-(NSString *)UTF8StringFromData:(NSData *)theData{ 
    Byte *arr = [theData bytes]; 
    NSUInteger begin1 = [self findIndexOf:@"<li>" bArr:arr size:[theData length]]+4; 
    NSUInteger end1 = [self findIndexOf:@"</li></ol>" bArr:arr size:[theData length]]; 
    Byte *arr1 = (Byte *)malloc(sizeof(Byte)*((end1-begin1+1))); 
    int j = 0; 
    for (int i = begin1; i < end1; i++){ 
     arr1[j] = arr[i]; 
     j++; 
    } 
    arr1[j]='\0'; 
    NSData *temp = [NSData dataWithBytes:arr1 length:j]; 
    return [[NSString alloc] initWithData:temp encoding:NSUTF8StringEncoding]; 
} 

y en segundo lugar - que estoy recibiendo el contenido del archivo de la web - por lo que no puedo estar seguro de nada. Es un HTML de una traducción de Google si ayuda ...

+0

nadie lo sabe? ... vamos ... Alguien debe haber encontrado esto antes de –

11

Suponiendo que tienes una respuesta NSURLResponse * * y un NSData datos:

CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef) [response textEncodingName]); 
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding); 

NSString* string = [[NSString alloc] initWithData:data encoding:encoding]; 

// Do stuff here.. 

[string release]; 
+0

Estoy usando xcode 4 con ARC habilitado para mi proyecto, y cuando uso el código anterior me queja de que 'Cast del tipo de puntero de Objective-C 'NSString * 'al tipo de puntero C' CFStringRef '(alias' const struct __CFString * ') requiere un reparto puenteado'. Cuando implementé cualquiera de las correcciones sugeridas (usando '__bridge' o' __bridge_retained') obtengo una señal EXC_BAD_ACCESS cuando se ejecuta el programa. ¿Algunas ideas? – Guss

+0

Debería ser '(__bridge CFStringRef) [response textEncodingName]'. Que ninguno de los dos trabajos me indica que el problema está en otra parte. Active NSZombieEnabled y use CFZombieLevel para rastrear el acceso a memoria desasignado. –

+0

gracias por la respuesta. Eso suena bastante complicado y soy un novato total en el desarrollo de iOS, pero lo verificaré. Eventualmente resolví el problema usando el horrible código: 'char * myenc = malloc ([responseEncoding length]); [[_response textEncodingName] getCString: myenc maxLength: codificación de [responseEncoding length]: NSASCIIStringEncoding]; CFStringRef encenc = CFStringCreateWithCString (kCFAllocatorDefault, myenc, kCFStringEncodingASCII); CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding (encenc); gratis (myenc); ' – Guss

1

Estoy respondiendo a la rosca Martijn lo anterior, aquí, ya que no pude poner un fragmento de código legible en los comentarios.

He descubierto que si en el servidor, el tipo de contenido de la respuesta está en 'text/plain', entonces (__bridge CFStringRef) [textEncodingName respuesta] será nulo, y si se intenta pasar esto a CFStringConvertIANACharSetNameToEncoding obtendrá una señal EXC_BAD_ACCESS.

Si el tipo de contenido de la respuesta está establecido en 'text/html; charset = utf-8 ', entonces todo funciona como se esperaba. Para manejar el tipo de contenido 'text/plain', esto es lo que hice:

CFStringRef sRef = (__bridge CFStringRef)[response textEncodingName]; 
if (sRef) 
{ 
     CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding(sRef); 
     encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding); 
} 
else 
{ 
     encoding = NSASCIIStringEncoding; 
}