2009-09-11 10 views
6

Je reçois un fichier html sous NSData et j'ai besoin de l'analyser pour en extraire quelques informations. Mon approche était de le convertir en NSString avec l'encodage UTF8 (le html a des caractères non anglais, le russe par exemple) - il a échoué. J'ai utilisé quelque chose comme ça:Problème de conversion NSData à NSString!

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

mais il est retourné à zéro.

La seule chose qui fonctionnait vraiment était

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

mais quand il rencontre des personnages russes par exemple, il retourne jibrish.

Ensuite, mon approche suivante consistait à analyser le tableau d'octets des données, extraire les octets dont j'avais besoin et les convertir en quelque sorte en NSString. J'ai essayé quelque chose comme ça:

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

* Êtes-vous sûr * que le fichier est encodé en UTF-8, et non pas comme ISO 8859-5 ou quelque chose? – Wevah

Répondre

0

Tout d'abord voici mon code

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

et seconde - Je reçois le contenu du fichier à partir du Web - donc je ne peux pas être sûr de quoi que ce soit. Il est un html d'une traduction google si elle aide ...

+0

personne ne le sait? ... viens ... Quelqu'un doit avoir rencontré ça avant –

11

Supposons que vous avez un NSURLResponse * réponse et une NSData * Données:

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

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

// Do stuff here.. 

[string release]; 
+0

J'utilise xcode 4 avec ARC activé pour mon projet, et quand j'utilise le code ci-dessus il se plaint que 'Cast du type de pointeur C-Objective 'NSString * 'à C type de pointeur' CFStringRef '(alias' const struct __CFString * ') nécessite un cast ponté. Lorsque j'ai implémenté l'une des corrections suggérées (en utilisant soit __bridge ou __bridge_retained), j'obtiens un signal EXC_BAD_ACCESS lorsque le programme s'exécute. Des idées? – Guss

+0

Il devrait être '(__bridge CFStringRef) [response textEncodingName]'. Que ni l'un ni l'autre ne m'indique que le problème est ailleurs. Activez NSZombieEnabled et utilisez CFZombieLevel pour localiser l'accès à la mémoire désalloué. –

+0

merci pour la réponse. Cela semble plutôt compliqué et je suis un total noob dans le développement iOS, mais je vais vérifier. J'ai finalement travaillé autour du problème en utilisant l'horrible code: 'char * myenc = malloc ([responseEncoding length]); [[_response textEncodingName] getCString: myenc maxLength: [encodage de longueur de réponse] codage: NSASCIIStringEncoding]; CFStringRef encenc = CFStringCreateWithCString (kCFAllocatorDefault, myenc, kCFStringEncodingASCII); CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding (encenc); gratuit (myenc); ' – Guss

1

Je réponds au fil Martijn qui précède, ici, comme je ne pouvais pas mettre un extrait de code lisible dans les commentaires.

J'ai trouvé que si sur le serveur, le type de contenu de réponse est défini sur 'text/plain', alors (__bridge CFStringRef) [response textEncodingName] sera null, et si vous essayez de passer cela à CFStringConvertIANACharSetNameToEncoding, vous obtiendrez un signal EXC_BAD_ACCESS.

Si le type de contenu de la réponse est défini sur 'text/html; charset = utf-8 ', alors tout fonctionne comme prévu. Pour gérer le type de contenu « text/plain », voilà ce que je l'ai fait:

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