将NSString转换为UTF32和从UTF32转换
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将NSString转换为UTF32和从UTF32转换相关的知识,希望对你有一定的参考价值。
我正在使用包含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 *吗?
任何帮助是极大的赞赏!
谢谢,罗恩
你有几个合理的选择。
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:
第一个是[NSString cStringUsingEncoding:]
和[NSString getCString:maxLength:encoding:]
在使用NSUTF32StringEncoding
和NSUTF16StringEncoding
时,在没有添加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.
要解决这个问题:
- 明确说明要使用两种方式的编码字节序(
NSString -> C-string
和C-string -> NSString
) - 尝试从UTF-32或UTF-16编码的C字符串创建NSString时,请使用
[NSString initWithBytes:length:encoding:]
。
希望这可以帮助!
以上是关于将NSString转换为UTF32和从UTF32转换的主要内容,如果未能解决你的问题,请参考以下文章
将 UTF-16(Windows 上的 wchar_t)转换为 UTF32
哪些开源 C 或 C++ 库可以将任意 UTF-32 转换为 NFC? [关闭]
C++11 字符转换 UTF-8 UTF-16 UTF-32 UNICODE 错误LINK2001