Может ли stringEncodingForData: encodingOptions: convertString: usedLossyConversion: вернуть NSUTF16StringEncoding или NSUTF32StringEncoding? - PullRequest
0 голосов
/ 29 октября 2018

Я хотел бы знать, может ли вызов stringEncodingForData:encodingOptions:convertedString:usedLossyConversion: вернуть NSUTF16StringEncoding, NSUTF32StringEncoding или любой из их вариантов?

Причина, по которой я спрашиваю, заключается в том, что примечание к документации по cStringUsingEncoding::

Особые замечания

UTF-16 и UTF-32 не считаются кодировками строки C и не должны использоваться с этим методом - результаты передачи NSUTF16StringEncoding , NSUTF32StringEncoding или любой их вариант не определен.

Итак, я понимаю, что создание строки C с UTF-16 или UTF-32 не поддерживается, но я не уверен, что попытка Обнаружение строкового кодирования с stringEncodingForData:encodingOptions:convertedString:usedLossyConversion: может вернуть UTF-16 и UTF -32 или нет.

Пример сценария (адаптированный из SSZipArchive.m ) может быть:

// name is a null-terminated C string built with `fread` from stdio.h:
char *name = (char *)malloc(size_name + 1);
size_t read = fread(name, 1, size_name + 1, file);
name[size_name] = '\0';

// dataName is the data object of name
NSData *dataName = [NSData dataWithBytes:(const void *)name length:sizeof(unsigned char) * size_name];

// stringName is the string object of dataName
NSString *stringName = nil;
NSStringEncoding encoding = [NSString stringEncodingForData:dataName encodingOptions:nil convertedString:&stringName usedLossyConversion:nil];

В приведенном выше коде могут encoding быть NSUTF16StringEncoding, NSUTF32StringEncoding или любой из их вариантов?


Платформы: macOS 10.10+, iOS 8.0+, watchOS 2.0+, tvOS 9.0+.

1 Ответ

0 голосов
/ 26 декабря 2018

Да, если строка закодирована с использованием одной из этих кодировок. Заметки о C-строках относятся к C-строкам. NSString не является строкой C, и метод, который вы описываете, не работает со строками C; он работает с произвольными данными, которые могут быть закодированы самыми разными способами.

Как пример:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSData *data = [@"test" dataUsingEncoding:NSUTF16StringEncoding];
        NSStringEncoding encoding = [NSString stringEncodingForData:data
                                                    encodingOptions:nil
                                                    convertedString:nil
                                                usedLossyConversion:nil];
        NSLog(@"%ld == %ld", (unsigned long)encoding, 
                             (unsigned long)NSUTF16StringEncoding);
    }
    return 0;
}
// Output:   10 == 10

В вашем конкретном примере сказано, что если name действительно то, что говорится, «строка C с нулевым символом в конце», то это никогда не может быть UTF-16, потому что строки C не могут быть закодированы в UTF- 16. Строки C заканчиваются на \ 0, а \ 0 - очень распространенный символ в UTF-16. Однако, не видя больше кода, я бы не рискнул, насколько точен этот комментарий.

Если ваш настоящий вопрос здесь «задан произвольной кодировкой, безопасной для c-строки, возможно ли, что stringEncodingForData: вернет кодировку, не безопасную для c-строки», тогда ответ «да, возможно, и определенно не обещано, что не будет, даже если не сегодня ». Если вам нужно это предотвратить, я рекомендую использовать NSStringEncodingDetectionSuggestedEncodingsKey и ...UseOnlySuggestedEncodingsKey, чтобы сделать его кодировкой, которую вы можете обрабатывать. (Вы также можете использовать ...DisallowedEncodingsKey для предотвращения определенных многобайтовых кодировок, но это не будет таким надежным.)

...