会python做网站seo是什么单位
为了理解编码,我们要先区分 文件中字符编码 和 程序运行时字符编码 的区别。
文件中字符编码 顾名思义 就是 文字保存在文件中的采用的字符编码方式,可以在IDE中看到程序运行时字符编码,是编译器读取从源文件中读取到字符串后再按要求做的一次字符编码转换后存入所采用的字符编码,这个字符编码转码过程是编译器编译时发生的,经过编译器生成的obj文件和exe中保存的字符串就是采用编码转换后的字符编码,也是运行时的字符编码,这个编码可能与源文件中不是同一种字符编码。
通过编译器参数finput-charset(gcc编译器)/source-charset(vs编译器)设置输入到编译器的源文件的字符编码,通过便器参数fexec-charset(gcc编译器)/execution-charset(vs编译器)设置目标文件中字符编码。
编译出来的程序 进行 文件读写 操作时 需要做额外操作, 特别是读取文件字节流 放入到QString中 时,需要明确知道文件中的字符编码,然后给与正确的转换。
文件编码和输出显示乱码有兴趣可以参考:qt 汉字输出 显示乱码 解决-CSDN博客
QString中只存放unicode的utf16编码的字符串,内部用QChar(short)类型的内存 进行 保存。
char*变量在内存中存放的字符串默认编码,与编译器参数 execution-charset有关,而vs2015及以下编译器默认为 "/execution-charset=GB2312",也就是char*变量内存中保存时使用ansi(具体为GB2312)编码,vs2022默认为 "/execution-charset=UTF-8",gcc或类gcc编译器默认为 "-fexec-charset=UTF-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-charset=UTF-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_cast<const ushort *>(str), size); }static QString fromUcs4(const char32_t *str, int size = -1){ return fromUcs4(reinterpret_cast<const 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() 也依赖QTextCodec,qt输出到控制台窗口时,会使用QTextCodec进行字符转码,然后再输出到控制台窗口。具体参考qt 汉字输出 显示乱码 解决-CSDN博客
简单案例:
#include <QTextCodec>
#include <QDebug>
#include <Windows.h>
int main()
{//QTextCodec编码器要与编译器参数execution-charset(vs编译器,默认为GB2312)/fexec-charset(gcc或类gcc编译器,默认为UTF8)的值一致,QTextCodec *codec=QTextCodec::codecForName("GB2312"); //设置QString的fromLocal8Bit() 和toLocal8Bit()的QTextCodec为GB2312QTextCodec//QTextCodec *codec=QTextCodec::codecForName("UTF-8"); //设置QString的fromLocal8Bit() 和toLocal8Bit()的QTextCodec为UTF-8 QTextCodecQTextCodec::setCodecForLocale(codec);QString s=QString::fromLocal8Bit("你好");//QString s=QString::fromUtf8(u8"你好"); //system("chcp 936"); //设置控制台输出窗口接收GB2312编码的字符串//system("chcp 65001"); //设置控制台输出窗口接收utf8编码的字符串qDebug()<<s<<endl;return 0;
}