2009-09-11 15 views
6

Tôi nhận được tệp html dưới dạng NSData và cần phân tích cú pháp để trích xuất một số thông tin. Cách tiếp cận của tôi là chuyển đổi nó thành NSString với mã hóa UTF8 (html có các ký tự không phải tiếng Anh, ví dụ như tiếng Nga) - nó không thành công. Tôi đã sử dụng một cái gì đó như thế:NSData để NSString vấn đề hội tụ!

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

nhưng nó trở lại không.

Điều duy nhất mà thực sự làm việc là

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

nhưng khi nó gặp nhân vật Nga ví dụ nó sẽ trả về jibrish.

Sau đó, cách tiếp cận tiếp theo của tôi là phân tích mảng byte của dữ liệu, trích xuất các byte tôi cần và bằng cách nào đó chuyển đổi chúng thành NSString. Tôi cố gắng một cái gì đó như thế:

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

Bạn có chắc chắn * * rằng các tập tin được mã hóa theo UTF-8, và không phải là tiêu chuẩn ISO 8859-5 hoặc một cái gì đó? – Wevah

Trả lời

0

Trước hết đây là mã của tôi

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

và thứ hai - Tôi nhận được các nội dung tập tin từ trang web - vì vậy tôi không thể chắc chắn về bất cứ điều gì. Đây là một html của một bản dịch google nếu nó giúp ...

+0

không ai biết? ... đi vào ... Ai đó phải đi qua cái này trước khi –

11

Giả sử bạn có một NSURLResponse * phản ứng và một NSData * dữ liệu:

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

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

// Do stuff here.. 

[string release]; 
+0

Tôi đang sử dụng xcode 4 với ARC được kích hoạt cho dự án của tôi, và khi tôi sử dụng đoạn mã trên nó phàn nàn rằng 'kiểu con trỏ Objective-C 'NSString * 'để C loại con trỏ' CFStringRef '(aka' const struct __CFString * ') đòi hỏi một cast cầu nối'. Khi tôi thực hiện bất kỳ sửa chữa được đề xuất nào (sử dụng '__bridge' hoặc' __bridge_retained'), tôi nhận được tín hiệu EXC_BAD_ACCESS khi chương trình chạy. Bất kỳ ý tưởng? – Guss

+0

Nó phải là '(__bridge CFStringRef) [response textEncodingName]'. Đó không phải là công trình chỉ ra cho tôi rằng vấn đề nằm ở nơi khác. Bật NSZombieEnabled và sử dụng CFZombieLevel để theo dõi truy cập bộ nhớ được phân bổ lại. –

+0

cảm ơn bạn đã trả lời. Điều đó nghe khá phức tạp và tôi là một tổng noob trong việc phát triển iOS, nhưng tôi sẽ kiểm tra nó. Cuối cùng tôi đã làm việc xung quanh vấn đề bằng cách sử dụng mã khủng khiếp: 'char * myenc = malloc ([responseEncoding length]); [[_response textEncodingName] getCString: myenc maxLength: [phản hồiĐộ dài mã hóa] mã hóa: NSASCIIStringEncoding]; CFStringRef encenc = CFStringCreateWithCString (kCFAllocatorDefault, myenc, kCFStringEncodingASCII); CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding (encenc); miễn phí (myenc); ' – Guss

1

Tôi đang trả lời các chủ đề Martijn ở trên, ở đây, vì tôi không thể đặt đoạn mã có thể đọc được trong các nhận xét.

Tôi thấy rằng nếu trên máy chủ, loại nội dung phản hồi được đặt thành 'text/plain', sau đó (__bridge CFStringRef) [response textEncodingName] sẽ là null và nếu bạn cố chuyển nó tới CFStringConvertIANACharSetNameToEncoding, bạn sẽ nhận được tín hiệu EXC_BAD_ACCESS.

Nếu loại nội dung của phản hồi được đặt thành 'text/html; charset = utf-8 ', sau đó mọi thứ hoạt động như mong đợi. Để xử lý các 'text/plain' kiểu nội dung, đây là những gì tôi đã làm:

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