繁体   English   中英

如何使用UTF-8编码将LPWSTR转换为char *

[英]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() ,返回的QStringQString::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM