2009-09-11 14 views
6

Otrzymuję plik html jako NSData i trzeba go przetworzyć, aby wyodrębnić pewne informacje. Moje podejście polegało na przekonwertowaniu go na NSString za pomocą kodowania UTF8 (html ma nie angielskie znaki, np. Rosyjski) - nie udało się. Użyłem czegoś takiego:Konwersja NSData do NSString!

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

ale zwrócono zero.

Jedyną rzeczą, która faktycznie przepracowanych było

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

ale gdy napotka rosyjski znaków na przykład zwraca jibrish.

Następnie moim następnym podejściem było przeanalizować tablicę bajtów danych, wyodrębnić potrzebne bajty i jakoś przekonwertować je na NSString. Próbowałem coś takiego:

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

Czy jesteś pewien, * * że plik jest zakodowany jako UTF-8, a nie jako ISO 8859-5 lub coś? – Wevah

Odpowiedz

0

Przede wszystkim tutaj jest mój kod

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

i drugie - jestem coraz zawartość pliku z internetu - więc nie mogę być pewny o cokolwiek. Jest to html z pomocną czy to pomaga ...

+0

nikt nie wie? ... chodź ... Ktoś musiał się z tym zapoznać przed –

11

Przypuśćmy, że masz NSURLResponse * Pasmo i NSData * dane:

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

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

// Do stuff here.. 

[string release]; 
+0

Używam xcode 4 z włączoną opcją ARC dla mojego projektu, a kiedy używam powyższego kodu, narzeka, że ​​'Cast z Objective-C wskaźnik typu 'NSString * "Typ wskaźnika C do C" CFStringRef "(inaczej" const struct __CFString * ") wymaga zmostkowanej obsady'. Kiedy zaimplementowałem którąś z sugerowanych poprawek (używając '__bridge' lub' __bridge_retained') otrzymuję sygnał EXC_BAD_ACCESS podczas działania programu. Jakieś pomysły? – Guss

+0

Powinien to być '(__bridge CFStringRef) [response textEncodingName]'. To, co nie działa, wskazuje mi, że problem leży gdzie indziej. Włącz NSZombieEnabled i użyj CFZombieLevel, aby wyśledzić zwolniony dostęp do pamięci. –

+0

dzięki za odpowiedź. To brzmi dość skomplikowanie i jestem totalnym noobem w rozwoju iOS, ale sprawdzę to. W końcu rozwiązałem ten problem, używając strasznego kodu: 'char * myenc = malloc ([responseEncoding length]); [[_response textEncodingName] getCString: myenc maxLength: kodowanie [lengthEncode length]: NSASCIIStringEncoding]; CFStringRef encenc = CFStringCreateWithCString (kCFAllocatorDefault, myenc, kCFStringEncodingASCII); CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding (encenc); za darmo (myenc); ' – Guss

1

mam odpowiadać na gwincie Martijn powyższym tutaj ponieważ nie mogłem umieścić czytelnego fragmentu kodu w komentarzach.

Znalazłem, że jeśli na serwerze typ zawartości odpowiedzi jest ustawiony na "text/plain", wówczas (__bridge CFStringRef) [response textEncodingName] będzie null, a jeśli spróbujesz przekazać to do CFStringConvertIANACharSetNameToEncoding, otrzymasz sygnał EXC_BAD_ACCESS.

Jeśli typ zawartości odpowiedzi jest ustawiony na "text/html; charset = utf-8 ', a następnie wszystko działa zgodnie z oczekiwaniami. Aby poradzić sobie z „text/plain” typ zawartości, to jest to, co zrobiłem:

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