python网站开发的优势,市住建局官方网,网上商城推广策略,冷门不重名的公司名称为了理解编码#xff0c;我们要先区分 文件中字符编码 和 程序运行时字符编码 的区别。 文件中字符编码 顾名思义 就是 文字保存在文件中的采用的字符编码方式#xff0c;可以在IDE中看到程序运行时字符编码#xff0c;是编译器读取从源文件中读取到字符串后再按要求做的一次…为了理解编码我们要先区分 文件中字符编码 和 程序运行时字符编码 的区别。 文件中字符编码 顾名思义 就是 文字保存在文件中的采用的字符编码方式可以在IDE中看到程序运行时字符编码是编译器读取从源文件中读取到字符串后再按要求做的一次字符编码转换后存入所采用的字符编码这个字符编码转码过程是编译器编译时发生的经过编译器生成的obj文件和exe中保存的字符串就是采用编码转换后的字符编码也是运行时的字符编码这个编码可能与源文件中不是同一种字符编码。 通过编译器参数finput-charset(gcc编译器)/source-charset(vs编译器)设置输入到编译器的源文件的字符编码通过便器参数fexec-charset(gcc编译器)/execution-charset(vs编译器)设置目标文件中字符编码。 编译出来的程序 进行 文件读写 操作时 需要做额外操作 特别是读取文件字节流 放入到QString中 时需要明确知道文件中的字符编码然后给与正确的转换。
文件编码和输出显示乱码有兴趣可以参考qt 汉字输出 显示乱码 解决-CSDN博客 QString中只存放unicode的utf16编码的字符串内部用QCharshort类型的内存 进行 保存。
char*变量在内存中存放的字符串默认编码与编译器参数 execution-charset有关而vs2015及以下编译器默认为 /execution-charsetGB2312也就是char*变量内存中保存时使用ansi(具体为GB2312)编码vs2022默认为 /execution-charsetUTF-8gcc或类gcc编译器默认为 -fexec-charsetUTF-8特就是char*使用unicode的utf8编码。可以通过在字符串前加u8强制编译器对某个char*变量在内存中保存时采用unicode的utf8编码。
char*转换成QString一定会做一次字符编码的转码 通过QString(const char*)构造的QString对象char*字符串会被QString强制当成unicode的 utf8编码这是QString代码不可更改的并隐式的将这个强制当做unicode 的utf8编码的字符串转换成unicode的utf16编码的字符串。vs编译器 的 execution-charset 默认 为ansi编码存放的编码为ansi编码如果你qt工程采用vs2015编译器或以下编译器这时候强制当做unicode的utf8转换成QString就一定会乱码所以这个时候最好设置/execution-charsetUTF-8的编译器参数。QString 官方不建议使用从char*转QString的构造函数。所以在这个构造函数前加了QT_ASCII_CAST_WARN 宏开关和宏提示。QString中所有的从char*转换到QString的构造函数 或者 由char*隐式转换到QString的函数 或者 参数中含有char*的非static函数 都是隐式调用QString::fromUtf8(char*) 这个静态函数 进行字符编码的转换的。从QByteArray转QString 与 char*转QString 是一样也会出现同样的问题
D:\Qt\Qt5.12.0\5.12.0\mingw73_64\include\QtCore\qstring.h
#if !defined(QT_NO_CAST_FROM_ASCII) !defined(QT_RESTRICTED_CAST_FROM_ASCII)
.......inline QT_ASCII_CAST_WARN QString(const char *ch): d(fromAscii_helper(ch, ch ? int(strlen(ch)) : -1)){}inline QT_ASCII_CAST_WARN QString(const QByteArray a): d(fromAscii_helper(a.constData(), qstrnlen(a.constData(), a.size()))){}inline QT_ASCII_CAST_WARN QString operator(const char *ch){ return (*this fromUtf8(ch)); }inline QT_ASCII_CAST_WARN QString operator(const QByteArray a)
......D:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\tools\qstring.cpp
......
QString::Data *QString::fromAscii_helper(const char *str, int size)
{QString s fromUtf8(str, size);s.d-ref.ref();return s.d;
}
......
从char*转到QString QString有提供很多的static类型的转码函数qt建议通过调用这些函数进行显示的编码转换。
D:\Qt\Qt5.12.0\5.12.0\mingw73_64\include\QtCore\qstring.hstatic inline QString fromLatin1(const QByteArray str)//从ascii编码转unicode的utf16编码{ return str.isNull() ? QString() : fromLatin1(str.data(), qstrnlen(str.constData(), str.size())); }static inline QString fromUtf8(const QByteArray str) //从unicode8的编码转换成unicode的utf16编码{ return str.isNull() ? QString() : fromUtf8(str.data(), qstrnlen(str.constData(), str.size())); }static inline QString fromLocal8Bit(const QByteArray str) //从local编码转换虫unicode的utf16编码{ return str.isNull() ? QString() : fromLocal8Bit(str.data(), qstrnlen(str.constData(), str.size())); }static QString fromUtf16(const ushort *, int size -1); //从unicode的utf16编码转unicode的utf16编码可以在字符串前存放BOM来指定输入的字符串字节序否则采用系统默认字节序static QString fromUcs4(const uint *, int size -1); //从unicode的utf32编码转unicode的utf16编码,可以在字符串前存放BOM来指定输入的字符串字节序否则采用系统默认字节序
#if defined(Q_COMPILER_UNICODE_STRINGS)static QString fromUtf16(const char16_t *str, int size -1){ return fromUtf16(reinterpret_castconst ushort *(str), size); }static QString fromUcs4(const char32_t *str, int size -1){ return fromUcs4(reinterpret_castconst uint *(str), size); }
#endif
fromutf16()和fromutf32()都可以在字符串前面加入BOM来明确告诉QString字节流所采用的字节序大小端。否则会被默认当做当前系统所采用的字节序。 下面是fromutf16中自动识别输入的字节流中的BOM并将输入字节流转换成本地字节序的unicode的utf16编码的过程。
D:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\tools\qstring.cpp
.......
QString QString::fromUtf16(const ushort *unicode, int size)
{if (!unicode)return QString();if (size 0) {size 0;while (unicode[size] ! 0)size;}return QUtf16::convertToUnicode((const char *)unicode, size*2, 0);
}
........D:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\codecs\qutfcodec_p.h
.......
enum DataEndianness
{DetectEndianness,BigEndianness,LittleEndianness
};
.......D:\Qt\Qt5.12.0\5.12.0\msvc2015_64\include\QtCore\qchar.h
......
class Q_CORE_EXPORT QChar {
public:enum SpecialCharacter {.......ByteOrderMark 0xfeff,ByteOrderSwapped 0xfffe,
........D:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\codecs\qutfcodec.cpp
........
QString QUtf16::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state, DataEndianness e DetectEndianness)
{DataEndianness endian e;bool half false;uchar buf 0;bool headerdone false;QChar *qch (QChar *)result.data();
......while (len--) {if (half) {QChar ch;if (endian LittleEndianness) {ch.setRow(*chars);ch.setCell(buf);} else {ch.setRow(buf);ch.setCell(*chars);}if (!headerdone) {headerdone true;if (endian DetectEndianness) {if (ch QChar::ByteOrderSwapped) {endian LittleEndianness;} else if (ch QChar::ByteOrderMark) {endian BigEndianness;} else {if (QSysInfo::ByteOrder QSysInfo::BigEndian) {endian BigEndianness;} else {endian LittleEndianness;ch QChar((ch.unicode() 8) | ((ch.unicode() 0xff) 8));}*qch ch;}} else if (ch ! QChar::ByteOrderMark) {*qch ch;}} else {*qch ch;}half false;} else {buf *chars;half true;}}
......
QTextCodec主要意义之一就是为QString的toLocal8BIt()和fromLocal8Bit(char*)设置字符编码器。QTextCodec可以通过预编译宏开关QT_NO_TEXTCODEC 进行开启或关闭默认开启。
fromLocal8Bit(char*)需要与QTextCodec结合使用否则输入的字节流会被当做ascii编码进行处理。fromLocal8Bit(char*)需要通过QTextCodec为QString指定字符编码器而该字符编码要与编译器所采用的编码保持一致也就是编译器参数 execution-charset(vs编译器参数) /fexec-charset(gcc编译器)所指定的编码保持一致
QString QString::fromLocal8Bit_helper(const char *str, int size)
{if (!str)return QString();if (size 0 || (!*str size 0)) {QStringDataPtr empty { Data::allocate(0) };return QString(empty);}
#if !defined(QT_NO_TEXTCODEC)if (size 0)size qstrlen(str);QTextCodec *codec QTextCodec::codecForLocale(); //获取到TextCodec设置的字符编码器if (codec)return codec-toUnicode(str, size);
#endif // !QT_NO_TEXTCODECreturn fromLatin1(str, size);
}
同样的QString 的 toLocal8BIt() 也依赖QTextCodecqt输出到控制台窗口时会使用QTextCodec进行字符转码然后再输出到控制台窗口。具体参考qt 汉字输出 显示乱码 解决-CSDN博客 简单案例
#include QTextCodec
#include QDebug
#include Windows.h
int main()
{//QTextCodec编码器要与编译器参数execution-charset(vs编译器默认为GB2312)/fexec-charset(gcc或类gcc编译器默认为UTF8)的值一致QTextCodec *codecQTextCodec::codecForName(GB2312); //设置QString的fromLocal8Bit() 和toLocal8Bit()的QTextCodec为GB2312QTextCodec//QTextCodec *codecQTextCodec::codecForName(UTF-8); //设置QString的fromLocal8Bit() 和toLocal8Bit()的QTextCodec为UTF-8 QTextCodecQTextCodec::setCodecForLocale(codec);QString sQString::fromLocal8Bit(你好);//QString sQString::fromUtf8(u8你好); //system(chcp 936); //设置控制台输出窗口接收GB2312编码的字符串//system(chcp 65001); //设置控制台输出窗口接收utf8编码的字符串qDebug()sendl;return 0;
}