2016-09-20 60 views
1

我当时玩弄了: https://stackoverflow.com/a/21575607/2416394中提到的代码,因为我有问题用TinyXML编写适当的utf8 xml。“Ü”的UTF编码返回3字节,而不是“真实”的unicode

好吧,我需要编码“拉丁大写字母U带二分法”,这是Ü要正确写入XML等

下面是代码以上述情况后:

std::string codepage_str = "Ü"; 
int size = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, codepage_str.c_str(), 
           codepage_str.length(), nullptr, 0); 
std::wstring utf16_str(size, '\0'); 
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, codepage_str.c_str(), 
        codepage_str.length(), &utf16_str[ 0 ], size); 

int utf8_size = WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), 
            utf16_str.length(), nullptr, 0, 
            nullptr, nullptr); 
std::string utf8_str(utf8_size, '\0'); 
WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), 
        utf16_str.length(), &utf8_str[ 0 ], utf8_size, 
        nullptr, nullptr); 

结果是一个的std :: string其具有3用下面的字节大小:当我将其写入到一个文件UTF8

-  utf8_str "Ü" std::basic_string<char,std::char_traits<char>,std::allocator<char> > 
     [size] 0x0000000000000003 unsigned __int64 
     [capacity] 0x000000000000000f unsigned __int64 
     [0] 0x55 'U' char 
     [1] 0xcc 'Ì' char 
     [2] 0x88 'ˆ' char 

。十六进制值保留在那里:0x55 0xCC 0x88和记事本++显示我正确的字符Ü

但是,当我通过Notepad ++将另一个Ü添加到文件并再次保存时,新写入的Ü显示为0xC3 0x9C(我实际上首先期望它)。

我不明白,为什么我得到这个字符的3字节表示,而不是预期的unicode codepoint U + 00DC。

虽然记事本++正确地显示出来,我们的专有系统通过渲染Ü没有认识到它作为一个两个字节的UTF-8

回答

6

统一是复杂的渲染上0x55 0xCC 0x880xC3 0x 9CÜ和休息。至少有两种不同的方式来获得Ü

  1. LATIN CAPITAL LETTER U WITH DIAERESIS是Unicode编码点U+00DC

  2. LATIN CAPITAL LETTER U是Unicode代码点U+0055COMBINING DIAERESIS是Unicode代码点U+0308

U+00DCU+0055 U+0308都显示为Ü

在UTF-8,Unicode的码点U+00DC被编码为0xC3 0x9CU+0055被编码为0x55,和U+0308被编码为0xCC 0x88

您的专有系统似乎有一个错误。

编辑:为了得到你所期望的,根据MultiByteToWideChar() documentation,使用MB_PRECOMPOSED而不是MB_COMPOSITE

+3

此外,这些不同形式之间的转换被称为[Unicode规范化](http://unicode.org/faq/normalization.html)。 – user694733

+0

@RemyLebeau:谢谢,这是一个更清洁。 – RemcoGerlich

2

虽然编码输出在技术上是正确的,但您可以使用NFC表单在专有系统中解决问题。

在NFC形式,所有字符首先被分解(例如,如果您有代码点U+00DCÜ,它会得到分解序列U+0055 U+0308),然后再由他们的规范表示(在你的榜样,为U+00DC )。

在Win32 API中,请参阅NormalizeString()函数。

相关问题