使用atlcov.h/W2A和中文文本的C++Utf-8转换
C++ Utf-8 conversion using atlconv.h / W2A and Chinese texts
我正在执行wchar_t*到UTF-8的转换,如下所示:
char* DupString(wchar_t* t)
{
if(!t) return strdup("");
USES_CONVERSION;
_acp = CP_UTF8;
return strdup(W2A(t));
}
通常情况下,它运行良好,但现在我找到了一个中文文本"主体"-转换无法正常工作。
宏本身的定义如下:
#define W2A(lpw) (
((_lpw = lpw) == NULL) ? NULL : (
(_convert = (lstrlenW(_lpw)+1),
(_convert>INT_MAX/2) ? NULL :
ATLW2AHELPER((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), _acp))))
在我的情况下_convert=2+1=3。传递给函数调用时,3*sizeof(WCHAR)=6。
在atlcov.h/AtlW2AHelper中,它命中WideCharToMultiByte,ret==0。
_Ret_opt_z_cap_(nChars) inline LPSTR WINAPI AtlW2AHelper(
_Out_opt_z_cap_(nChars) LPSTR lpa,
_In_opt_z_ LPCWSTR lpw,
_In_ int nChars,
_In_ UINT acp) throw()
{
ATLASSERT(lpw != NULL);
ATLASSERT(lpa != NULL);
if (lpa == NULL || lpw == NULL)
return NULL;
// verify that no illegal character present
// since lpa was allocated based on the size of lpw
// don't worry about the number of chars
*lpa = ' ';
int ret = WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL);
if(ret == 0)
{
ATLASSERT(FALSE);
return NULL;
}
return lpa;
}
@"监视"窗口中的err显示错误代码122=error_INSUFFIENT_BUFFER。
我已经尝试将缓冲区增加一个字节-nChar=7-然后转换成功。缓冲区填充了6个字节+1个ascii零终止,因此填充了7个字节。
这是W2A宏的一个错误吗?没有考虑ascii零?
有人见过类似的问题吗?
作为一个平台,我正在使用visualstudio2010,不确定其他visualstudio是否也存在问题。
在一些头文件中,这个问题似乎已经解决了——例如:
https://github.com/kxproject/kx-audio-driver/blob/master/h/gui/kDefs.h
但它适用于某些第三方项目,而不是Visual studio本身。
W2A
错误地认为每个字符两个字节的缓冲区就足以进行转换。您的字符串扩展为一个包含七个字节的UTF-8字符串,其中包括以零结尾的字符串。WideCharToMultiByte
因缓冲区不足而失败-这是您已经发现的。
它看起来像是一个你可以在atlcov.h:中自己修复的错误(微软不会更新VS 2010,我想更新到2015年可能已经晚了)
#define W2A(lpw) (
((_lpw = lpw) == NULL) ? NULL : (
(_convert = (static_cast<int>(wcslen(_lpw))+1),
(_convert>INT_MAX/2) ? NULL :
ATLW2AHELPER((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*4, _acp)))) //sizeof(WCHAR), _acp))))
或者,您可以使用更新的CW2A
转换宏,这些宏已经分配了更大的缓冲区(每个字符4个字节,请参阅CW2AEX::Init
):
static const LPCWSTR g_psz = L"主体";
LPCSTR psz = _strdup(CW2A(g_psz, CP_UTF8));
从Microsoft论坛复制粘贴,从这里:
https://social.msdn.microsoft.com/Forums/en-US/262e7b83-8cf4-45ed-a3db-5dc6064612f2/c-utf8-conversion-using-atlconvh-w2a-and-chinese-texts?forum=vcgeneral&prof=所需
您是否考虑过使用改进的ATL7宏?https://msdn.microsoft.com/en-us/library/87zae4a3.aspx#atl70stringconversionclassesmacros
CW2A pA( pW, CP_UTF8 );
这似乎假设每个Unicode字符最多4个字节,而不是2个老的那个。
这似乎是字符串的更好用法,因为CW2A的析构函数将释放转换缓冲区。
wchar_t* pStr = NULL;
{
CW2A pA( pW, CP_UTF8 );
pStr = pA;
// pStr is valid
}
// pStr is invalid
- 如何将 UTF-8 文本从文件转换为某个可以迭代的容器,并检查每个符号是否为C++字母数字?
- 通过分隔符分隔包含 UTF-16 BE 文本的uint8_t数组
- 如何在C 17中读取UTF-16文本文件
- UTF-16LE 编码问题与 Qt 文本编辑器用 C++ 编写
- Arduino UCS2至UTF文本形式
- 有关读取 UTF-8 编码文本时 Ifstream get() 方法行为的说明 (C++)
- 使用标准C++无线流读取UTF-8文本并转换为UTF-16
- 为什么我不能在窗口上使用 boost::locale::conv::between 将 UTF-16 文本转换为其他编码
- 使用atlcov.h/W2A和中文文本的C++Utf-8转换
- 从包含 utf-8(印地语)格式文本的文件读取并写入其他文件
- 字符类型并将 ASCII 文本重新编码为 UTF-16
- 在编译/运行时将字符串文本的原始字节流入/流出Windows(非宽)执行字符集,以及ANSI代码页与UTF-8
- 在没有外部库的情况下将 utf-16 文本文件正确读取到字符串中
- 我可以使用哪个库发送包含UTF文本和文件附件的SMTP/MIME电子邮件
- 如何检查文本文件是否使用UTF-8编码
- 如何将std::string中包含utf-16编码的文本转换为utf-16 wstring
- c++中utf -16编码文本的截断读取
- 如何在UTF-8文本中搜索行结束符(' ') ?
- 什么是用于 UTF-8/UTF-16 文本编码C++小型 LGPL 库?
- C++11:普通字符串文本和 UTF-8 字符串文本之间的差异示例