将NSString转换为UTF32和从UTF32转换

问题描述 投票:4回答:2

我正在使用包含UTF32字符的十六进制代码的数据库。我想把这些字符存储在NSString中。我需要有两种方式转换的例程。

要将NSString的第一个字符转换为unicode值,此例程似乎有效:

const unsigned char *cs = (const unsigned char *)
    [s cStringUsingEncoding:NSUTF32StringEncoding];
uint32_t code = 0;
for ( int i = 3 ; i >= 0 ; i-- ) {
    code <<= 8;
    code += cs[i];
}
return code;

但是,我无法做反向(即采用单个代码并将其转换为NSString)。我想我可以通过简单地创建一个带有UTF32字符的c字符串,并按照正确的顺序使用字节,然后使用正确的编码从中创建一个NSString。

但是,转换到cstrings /从cstrings转换对我来说似乎并不可逆。

例如,我尝试过这段代码,“tmp”字符串不等于原始字符串“s”。

char *cs = [s cStringUsingEncoding:NSUTF32StringEncoding];
NSString *tmp = [NSString stringWithCString:cs encoding:NSUTF32StringEncoding];

有谁知道我做错了什么?我应该使用“wchar_t”作为cstring而不是char *吗?

任何帮助是极大的赞赏!

谢谢,罗恩

iphone ios unicode
2个回答
14
投票

你有几个合理的选择。

1.转换

第一种是将UTF32转换为UTF16并使用NSString,因为UTF16是NSString的“本机”编码。实际上并不是那么难。如果UTF32字符在BMP中(例如,它的高两个字节是0),您可以直接将它转换为unichar。如果它在任何其他平面中,您可以将其转换为代表性的UTF16字符对。你可以在wikipedia page找到规则。但是快速(未经测试)的转换看起来像

UTF32Char inputChar = // my UTF-32 character
inputChar -= 0x10000;
unichar highSurrogate = inputChar >> 10; // leave the top 10 bits
highSurrogate += 0xD800;
unichar lowSurrogate = inputChar & 0x3FF; // leave the low 10 bits
lowSurrogate += 0xDC00;

现在,您可以同时使用两个字符创建NSString:

NSString *str = [NSString stringWithCharacters:(unichar[]){highSurrogate, lowSurrogate} length:2];

要向后移动,你可以使用[NSString getCharacters:range:]来获取unichar的背面,然后反转代理对算法以获得你的UTF32字符(任何不在0xD800-0xDFFF范围内的字符都应该直接转换为UTF32)。

2.字节缓冲区

您的另一个选择是让NSString直接执行转换而不使用cStrings。要将UTF32值转换为NSString,您可以使用以下内容:

UTF32Char inputChar = // input UTF32 value
inputChar = NSSwapHostIntToLittle(inputChar); // swap to little-endian if necessary
NSString *str = [[[NSString alloc] initWithBytes:&inputChar length:4 encoding:NSUTF32LittleEndianStringEncoding] autorelease];

要再次取消它,您可以使用

UTF32Char outputChar;
if ([str getBytes:&outputChar maxLength:4 usedLength:NULL encoding:NSUTF32LittleEndianStringEncoding options:0 range:NSMakeRange(0, 1) remainingRange:NULL]) {
    outputChar = NSSwapLittleIntToHost(outputChar); // swap back to host endian
    // outputChar now has the first UTF32 character
}

1
投票

这里有两个问题:

1:

第一个是[NSString cStringUsingEncoding:][NSString getCString:maxLength:encoding:]在使用NSUTF32StringEncodingNSUTF16StringEncoding时,在没有添加BOM的情况下以原始字节序(小)返回C字符串。

The Unicode standard states that :(参见“我应该如何处理物料清单”)

"If there is no BOM, the text should be interpreted as big-endian."

这也在NSString's documentation中说明:(参见“解释UTF-16编码数据”)

"... if the byte order is not otherwise specified, NSString assumes that the UTF-16 characters are big-endian, unless there is a BOM (byte-order mark), in which case the BOM dictates the byte order."

虽然它们指的是UTF-16,但同样适用于UTF-32。

2:

第二个是[NSString stringWithCString:encoding:]内部使用CFStringCreateWithCString来创建C字符串。这个问题是CFStringCreateWithCString只接受使用8位编码的字符串。来自documentation :(参见“参数”部分)

The string must use an 8-bit encoding.

要解决这个问题:

  1. 明确说明要使用两种方式的编码字节序(NSString -> C-stringC-string -> NSString
  2. 尝试从UTF-32或UTF-16编码的C字符串创建NSString时,请使用[NSString initWithBytes:length:encoding:]

希望这可以帮助!

© www.soinside.com 2019 - 2024. All rights reserved.