[英]How to convert LPWSTR to char * with UTF-8 encoding
我正在使用Qt开发跨平台项目。 在Windows上,我想从命令行启动应用程序时传递一些Unicode字符(例如,包含中文字符的文件路径)作为参数。 然后使用这些参数创建QCoreApplication
。
出于某些原因,我需要使用CommandLineToArgvW
来获取参数列表,如下所示:
LPWSTR * argvW = CommandLineToArgvW( GetCommandLineW(), &argc );
我理解在现代Windows操作系统上, LPWSTR
实际上是wchar_t*
,它是16位并使用UTF-16编码。
如果我想初始化QCoreApplication
,它只需要char*
而不是wchar_t*
。 QCoreApplication
所以问题是:如何安全地将CommandLineToArgvW()
函数返回的LPWSTR
转换为char*
而不会丢失UNICODE编码(例如中文字符仍然是中文字符)?
我尝试了许多不同的方法但没有成功:
1:
std::string const argvString = boost::locale::conv::utf_to_utf<char>( argvW[0] )
2:
int res;
char buf[0x400];
char* pbuf = buf;
boost::shared_ptr<char[]> shared_pbuf;
res = WideCharToMultiByte(CP_UTF8, 0, pcs, -1, buf, sizeof(buf), NULL, NULL);
3:首先转换为QString,然后转换为UTF-8。
ETID:问题解决了。 对于UTF-8 char
转换的UTF-16宽字符实际上工作正常而没有所有这三种方法的问题。 在Visual Studio中,为了在调试中正确查看UTF-8字符串,必须在监视变量名后附加s8
格式说明符(请参阅: https : //msdn.microsoft.com/en-us/library/ 75w45ekt.aspx )。 这是我忽略的部分,让我觉得我的字符串转换是错误的。
这里真正的问题实际上是在调用QCoreApplication.arguments()
,返回的QString
由QString::fromLocal8Bit()
构造,当命令行参数包含unicode字符时,这将导致Windows上的编码问题。 解决方法是在必要时在Windows上检索命令行参数,始终调用Windows API CommandLineToArgvW()
,并将16位UTF-16 wchar_t *(或LPWSTR)转换为8位UTF-8 char *(由一个中提到的三种方式)。
你应该能够使用QString
的功能。 例如
QString str = QString::fromUtf16((const ushort*)argvW[0]);
::MessageBoxW(0, (const wchar_t*)str.utf16(), 0, 0);
使用WideCharToMultiByte
,为输出缓冲区和输出缓冲区的长度传递零。 这将告诉您输出缓冲区需要多少个字符。 例如:
const wchar_t* wbuf = argvW[0];
int len = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, 0, 0, 0, 0);
std::string buf(len, 0);
WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, &buf[0], len,0,0);
QString utf8;
utf8 = QString::fromUtf8(buf.c_str());
::MessageBoxW(0, (const wchar_t*)utf8.utf16(), 0, 0);
QCoreApplication::arguments
应该提供相同的信息。 例如,使用Unicode参数运行此代码并查看输出:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString filename = QString::fromUtf8("ελληνική.txt");
QFile fout(filename);
if (fout.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream oss(&fout);
oss.setCodec("UTF-8");
oss << filename << "\n";
QStringList list = a.arguments();
for (int i = 0; i < list.count(); i++)
oss << list[i] << "\n";
}
fout.close();
return a.exec();
}
请注意,在上面的示例中,文件名在内部转换为UTF-16,由Qt完成。 WinAPI使用UTF-16,而不是UTF-8
Qt内部包装int main()
,在执行任何代码之前提取和解析Unicode命令行参数(通过CommandLineToArgvW
)。 生成的解析数据通过等效的QString::toLocal8Bit()
转换为char **argv
的本地UTF-8格式。
使用QCoreApplication::arguments()
来检索Unicode args。 另外,来自文档的有用说明:
在Windows上,仅当修改的argv / argc参数传递给构造函数时,才会使用argc和argv参数构建列表。 在这种情况下,可能会出现编码问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.