• 11726阅读
  • 6回复

[原创]Qt读取中文文件乱码解决方案 4和5都支持 [复制链接]

上一主题 下一主题
离线cangyuegui
 

只看楼主 倒序阅读 楼主  发表于: 2015-11-25

读取
获得文件内容
  1. QByteArray getFileContent(const QString &file)
  2. {
  3.     if (!QFile::exists(file))
  4.     {
  5.         qDebug()<<"ERROR, File "<<file<<" Not Exists !";
  6.         return QByteArray(NULL);
  7.     }
  8.     QFile dstFile(file);
  9.     if (!dstFile.open(QIODevice::Text | QIODevice::ReadOnly))
  10.     {
  11.         qDebug()<<"ERROR, File "<<file<<" Open Failure !";
  12.         return QByteArray(NULL);
  13.     }
  14.     QByteArray res = dstFile.readAll();
  15.     dstFile.close();
  16.     return res;
  17. }


转码
  1. QString convertToSytemEncode(const QByteArray &srcString)
  2. {
  3.     QTextCodec* pTextCodec = QTextCodec::codecForName("System");
  4.     if (NULL == pTextCodec)
  5.     {
  6.         return "";
  7.     }
  8.     return pTextCodec->toUnicode(srcString);
  9. }




保存GB2312一样的
  1. QByteArray encodeToSytemCodec(const QString &srcString)
  2. {
  3.     static QTextCodec * codec = QTextCodec :: codecForName ("System");
  4.     if (NULL == codec)
  5.     {
  6.         return "";
  7.     }
  8.     QByteArray encodedString = codec-> fromUnicode (srcString);
  9.     return encodedString;
  10. }

tips:
ps1 上面函数中的System只有qt4才支持这个编码,会根据系统不同而不同,window下则是gb2312编码.如果使用qt5请自行修改为gb2312.倒地支持哪些,请在assitant中自行查找
ps2 linux一般文档可能是utf-8,到底是什么编码qt不提供这个函数,无法确定的时候请用iconv自行判断
ps3 gb2312文本的代码中可以放中文注释,utf文件的话,有中文可能会导致编译错误.另外代码体中不能有任何中文,否则可能会引起无法预料的错误.
ps4 不要使用什么三句话解乱码这种狗屁方案,而且这种方案的话,qt5也用不了

博客里面 有比较粗略的函数
http://blog.csdn.net/fei17n/article/details/49887981
离线dbzhang800

只看该作者 1楼 发表于: 2015-11-25
被你标题吸引进来的,看到你的内容和标题出入比较大,简单说两句。

你文中内容似乎只是在试图解决一个问题:简体中文Windows下读取gbk编码的文本文件,Linux下读取utf8编码的文本文件。(而这个,对大家来说,其实不是问题。中文乱码的根源和难点都不在这儿)

单单就Windows来说:

中文文本文件可以是GB18030 / Big5 / Utf8 / Utf16-be / Utf16-le / Utf32-be / Utf32-le 等编码保存的。
而Windows下的System编码是由区域和语言设置所决定的。只不过在简体中文系统下用的GBK / GB18030罢了

你后面提到的4点,基本看不懂。特别是ps3和ps4,你到底是在描述读文件,还是在描述你的源码文件呢? 感觉上,你在推荐在VS环境下使用gb2312作为源码文件,而且你没有用过其他国家和地区的Windows编译过你的代码。
离线cangyuegui

只看该作者 2楼 发表于: 2015-11-25
被你标题吸引进来的,看到你的内容和标题出入比较大,简单说两句。

你文中内容似乎只是在试图解决一个问题:简体中文Windows下读取gbk编码的文本文件,Linux下读取utf8编码的文本文件。(而这个,对大家来说,其实不是问题。中文乱码的根源和难点都不在这儿)

第一:这两个只是个例子,实际上任何qt支持的编码都没问题,而且这个是codec插件做的,可以自己编写替换,所以可以做到任意编码都支持.

单单就Windows来说:

中文文本文件可以是GB18030 / Big5 / Utf8 / Utf16-be / Utf16-le / Utf32-be / Utf32-le 等编码保存的。
而Windows下的System编码是由区域和语言设置所决定的。只不过在简体中文系统下用的GBK / GB18030罢了

第二:这个文中有对立或者错误的地方么?

你后面提到的4点,基本看不懂。特别是ps3和ps4,你到底是在描述读文件,还是在描述你的源码文件呢? 感觉上,你在推荐在VS环境下使用gb2312作为源码文件,而且你没有用过其他国家和地区的Windows编译过你的代码。

第三:ps3属于tip,说明gb2312代码下,文本注释中写入中文,是安全的,而其他编码,是可能导致编译错误的.这段描述的是源代码文件.
顺便也说了不要使用这个方案:QStringLiteral("中文")(部分编码下这样的代码可能引起编译错误,而且和cpp文件本身的编码有关系,不通用,建议使用tr+qm)

第四:用哪个国家的windows编译代码根本不是问题,vs是可以手动调编码的,调了gb2312一样认.

第五:ps4是指不要使用这个方案
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
解决中文乱码问题,但是QT5却对以上函数中的两个已经不支持。
这个方案,在非中文windows下面真的会出问题,而且几乎任意非window平台都会出问题.


最后:乱码的根源是编码不一致.qt使用的是unicode,但是系统里面的文件指不定什么的.对于未知文本文件,文中解决方案是,使用iconv判断.
对于数据库里面产生的乱码,通常是两种问题
1.数据库内部做到编码转换
2.数据库内部存储的不是unicode,但是读取出来后未做转码处理

对于1 只能自求多福,除非摸清楚他怎么转的.
对于二,转个码就行了.


离线dbzhang800

只看该作者 3楼 发表于: 2015-11-25
首先:你的标题和贴中代码 都是说 读取中文文件乱码的解决方案。这和你tips中提到的C++源码采用何种编码,是两个既然不同的问题。

第一:这两个只是个例子,实际上任何qt支持的编码都没问题,而且这个是codec插件做的,可以自己编写替换,所以可以做到任意编码都支持.


Qt肯定可以读取任何它支持的编码的中文文件,这没人否认。但是乱码根源在于,你不知道读取的中文文件是何种编码。


第二:这个文中有对立或者错误的地方么?


你首帖中说的是:window下则是gb2312编码。事实上只有简体中文Windows下如此

第三:ps3属于tip,说明gb2312代码下,文本注释中写入中文,是安全的,而其他编码,是可能导致编译错误的.这段描述的是源代码文件.
顺便也说了不要使用这个方案:QStringLiteral("中文")(部分编码下这样的代码可能引起编译错误,而且和cpp文件本身的编码有关系,不通用,建议使用tr+qm)


呵呵,我是提倡用tr+qm的,但是提倡并不能解决问题。

你这儿描述的东西,只是你在简体中文windows下用VS2005及以上版本时,看到的一种表象。如果你知道了出错原因是什么,问题自然就明朗了。

gb2312远远没有你想象的好用。

第四:用哪个国家的windows编译代码根本不是问题,vs是可以手动调编码的,调了gb2312一样认.


说实话,这个似乎有点意思。VS下C++的编译器是 cl.exe,我还真不知道它有可以控制C++源码文件编码的选项。

第五:ps4是指不要使用这个方案
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
解决中文乱码问题,但是QT5却对以上函数中的两个已经不支持。
这个方案,在非中文windows下面真的会出问题,而且几乎任意非window平台都会出问题


嗯,我应该算是该用法强烈的抵制者(之一)吧。但在Qt4时期,网络上国内这种错误用法太多了。

不过,平心而论,直接用GBK这种还算是稍微好的了(比system那种好多了)。而且在非windows平台下,也不会有多大问题。

最后:乱码的根源是编码不一致.qt使用的是unicode,但是系统里面的文件指不定什么的.对于未知文本文件,文中解决方案是,使用iconv判断.


乱码的根源是不知道编码,而不是不一致。
对于一个文本文件来说,如果不知道它的编码,理论上是猜不出它的编码的,任何工具都没有用。

离线cangyuegui

只看该作者 4楼 发表于: 2015-11-26
回 dbzhang800 的帖子
dbzhang800:首先:你的标题和贴中代码 都是说 读取中文文件乱码的解决方案。这和你tips中提到的C++源码采用何种编码,是两个既然不同的问题。
乱码的根源是不知道编码,而不是不一致。
....... (2015-11-25 22:12) 

那个system只是个例子啊

iconv可以判断出绝大部分编码,就想文本编辑器和notepad++打开文本一般不会乱码一样
但是并不是万能的

著名的 "联通" 乱码,这种是无能无力的.

代码中混入中文编译错误的原因,是因为编译器一般会把源码当做单字节读取,会把中文读成乱七八糟的东西.

不过题目确实不是很严谨
离线dbzhang800

只看该作者 5楼 发表于: 2015-11-26
VS的的问题出在,Windows内部早就是unicode了,但是它又不愿意放弃和老旧代码的兼容性。从VS2005开始,如果源码文件不带BOM,它会默认你用的本地字符集,而且在编译正式开始前,它内部先将源码文件解码成unicode,而后进行处理。具体到简体中文Windows下,就是它会用GBK去解码你的源文件,而不管你实际用的是GBK/utf8/还是其他编码。

而有意思之处在于,用gbk解码utf8或其他编码文件,很多时候是可以成功的,尽管结果是乱的。

VS复杂之处在于:VS2003/2005/2008/2010/2012 ,行为各不相同。好在Qt5选定了默认utf8,使得问题可以简化很多。
离线cangyuegui

只看该作者 6楼 发表于: 2015-11-26
回 dbzhang800 的帖子
dbzhang800:VS的的问题出在,Windows内部早就是unicode了,但是它又不愿意放弃和老旧代码的兼容性。从VS2005开始,如果源码文件不带BOM,它会默认你用的本地字符集,而且在编译正式开始前,它内部先将源码文件解码成unicode,而后进行处理。具体到简体中文Windows下,就是它会用GBK去解码你的 .. (2015-11-26 10:17) 

岂止行为不一样

语法都不一样
快速回复
限100 字节
 
上一个 下一个