c++中文编码问题
std::string或者const char*,本质上都是二进制,不包含编码属性,其编码信息来源于赋值语句,
QString以utf16编码,默认构造或赋值的字面量假定为utf8,若是其它编码比如ansi,可以调用QString::fromLocal8bit
一、字面量的编码取决于文件,即如果在c++源文件中有直接赋值
1)、const char* s="中文";或者std::string str="中文",该源文件是什么编码,则结果就是什么编码。
2)、QString默认以utf-16编码,默认赋值假定为utf8,即:若源文件为utf8编码,则QString qStr="中文"
若源文件为ansi,则QString qStr=QString::fromLocal8bit(”中文")
可以用记事本打开源文件,点另存为
二、printf和std::cout
的编码取决于codepage,windows默认为ansi,查看方式,点左上角,属性
控制台应用,可以通过在main开始处设置utf8:
system("chcp 65001");//utf-8
三、main的argv到底是什么编码----ansi,无论调用system("chcp 65001")否。
四、调试过程中只能显示ansi,如果const char* 或者std::string编码为utf8,调试显示会乱码
解决方式:可在watch中查看该变量,后加",s8"
五、qt 5.15 后,QString::toStdString()和qDebug()默认调用toUtf8(),即将utf16转换为utf8。
QTextCodec::setCodecForLocale只对QString::toLocalUtf8发生作用,
中文操作系统默认: QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
六、gdal:
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES/NO");
若为YES,则假定函数接收的路径变量为utf8编码的,否则为ansi的。
七、osg:
若在CMake编译的时候就选择OSG_USE_UTF8_FILENAME选项,则osgdb命名空间里read write路径均假定为utf8,否则为ansi
例:
int main(int argc, char* argv[]) {
#if 1
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
GDALAllRegister();
//system("chcp 65001");
if (argc < 10)return 0;
//因为argv编码与源文件编码无关,一定为ansi,而qstring赋值语句默认接受utf8,因此需调用fromLocal8Bit
QString tiffPath =QString::fromLocal8Bit( argv[10]);//假定tiff路径存在命令行第10个参数中
//qDebug()解码为utf8
qDebug() << tiffPath.toStdString().c_str();
//tiffPath为utf16编码,toStdString默认调用toUtf8,则接受的输入符合GDAL_FILENAME_IS_UTF8=YES
GDALDataset* tiffDs=(GDALDataset *) GDALOpen(tiffPath.toStdString().c_str(), GDALAccess::GA_ReadOnly);
////一、源文件为utf编码时:
////因为源文件是utf8编码,则osgPath也是utf8编码,此时调试osgPath显示乱码,可watch ,s8
//std::string osgPath = "D:\\osgdataTest\\OSGB\\OSGB中\\Data\\rootMerge\\rootMerge.osgb";
////因为之前设置了system("chcp 65001"),则可正确显示中文
//std::cout << osgPath << "\n";
//二、源文件为ansi编码时:
//因为源文件是ansi编码,则osgPath也是ansi编码,此时调试osgPath显示正确
std::string osgPath = "D:\\osgdataTest\\OSGB\\OSGB中\\Data\\rootMerge\\rootMerge.osgb";
//fromLocal8Bit将ansi转换为utf16,toStdString再转换为utf8
osgPath = QString::fromLocal8Bit(osgPath.c_str()).toStdString();
//因为之前设置了system("chcp 65001"),则可正确显示中文
std::cout << osgPath << "\n";
//若osg库是打开utf8编译选项的,则以下可以执行
osg::Node* node = osgDB::readNodeFile(osgPath);
return 0;
#endif
}
以上一二分别对应源文件为utf8编码或者ansi编码