Документы для NSString getCString: maxLength: кодировка говорит:
Вы можете использовать canBeConvertedToEncoding: чтобы проверить, может ли быть строка
без потерь конвертируется в кодировку. Если это не так, вы можете использовать
dataUsingEncoding: allowLossyConversion: получить C-строку
представление с использованием кодирования, допускающего некоторую потерю информации (примечание
что данные, возвращаемые dataUsingEncoding: allowLossyConversion: is
не строгая C-строка, так как она не имеет нулевого терминатора).
Использование метода NSString dataUsingEncoding: allowLossyConversion: делает свое дело. Вот пример кода:
NSString *myAccentStr = @"José";
char str[[myAccentStr length] + 1];
// NSString * to C String (char*)
NSData *strData = [myAccentStr dataUsingEncoding:NSMacOSRomanStringEncoding
allowLossyConversion:YES];
memcpy(str, [strData bytes], [strData length] + 1);
str[[myAccentStr length]] = '\0';
NSLog(@"str (from NSString* to c string): %s", str);
// C String (char*) to NSString *
NSString *newAccentStr = [NSString stringWithCString:str
encoding:NSMacOSRomanStringEncoding];
NSLog(@"newAccentStr (from c string to NSString*): %@", newAccentStr);
Вывод этого NSLog:
str (от NSString * до c string): Хосе
newAccentStr (от строки c до строки NSString): Хосе
До сих пор я видел эту работу правильно только при использовании NSMacOSRomanStringEncoding.
Редактировать
Изменение этого вики сообщества. Пожалуйста, не стесняйтесь редактировать.
У hooleyhoop есть несколько замечательных моментов, поэтому я подумал, что постараюсь сделать код максимально подробным. Если я что-то упустил, пожалуйста, включите.
Также - Не уверен, почему [NSString canBeConvertedToEncoding:] возвращает YES, даже если функция [NSString getCString: maxLength: encoding:] определенно работает неправильно (как видно из выходных данных).
Вот некоторый код, помогающий проанализировать, что работает, а что нет:
// Define Block variable to tests out different encodings
void (^tryGetCStringUsingEncoding)(NSString*, NSStringEncoding) = ^(NSString* originalNSString, NSStringEncoding encoding) {
NSLog(@"Trying to convert \"%@\" using encoding: 0x%X", originalNSString, encoding);
BOOL canEncode = [originalNSString canBeConvertedToEncoding:encoding];
if (!canEncode)
{
NSLog(@" Can not encode \"%@\" using encoding %X", originalNSString, encoding);
}
else
{
// Try encoding using NSString getCString:maxLength:encoding:
NSUInteger cStrLength = [originalNSString lengthOfBytesUsingEncoding:encoding];
char cstr[cStrLength];
[originalNSString getCString:cstr maxLength:cStrLength encoding:encoding];
NSLog(@" Converted(1): \"%s\" (expected length: %u)",
cstr, cStrLength);
// Try encoding using NSString dataUsingEncoding:allowLossyConversion:
NSData *strData = [originalNSString dataUsingEncoding:encoding allowLossyConversion:YES];
char cstr2[[strData length] + 1];
memcpy(cstr2, [strData bytes], [strData length] + 1);
cstr2[[strData length]] = '\0';
NSLog(@" Converted(2): \"%s\" (expected length: %u)",
cstr2, [strData length]);
}
};
NSString *myAccentStr = @"José";
// Try out whatever encoding you want
tryGetCStringUsingEncoding(myAccentStr, NSUTF8StringEncoding);
tryGetCStringUsingEncoding(myAccentStr, NSUTF16StringEncoding);
tryGetCStringUsingEncoding(myAccentStr, NSUTF32StringEncoding);
tryGetCStringUsingEncoding(myAccentStr, NSMacOSRomanStringEncoding);
Результаты:
> Trying to convert "José" using encoding: 0x4
> Converted(1): "" (expected length: 5)
> Converted(2): "José" (expected length: 5)
> Trying to convert "José" using encoding: 0xA
> Converted(1): "" (expected length: 8)
> Converted(2): "ˇ˛J" (expected length: 10)
> Trying to convert "José" using encoding: 0x8C000100
> Converted(1): "" (expected length: 16)
> Converted(2): "ˇ˛" (expected length: 20)
> Trying to convert "José" using encoding: 0x1E
> Converted(1): "-" (expected length: 4)
> Converted(2): "José" (expected length: 4)