Qt保存QStandardItemModel的数据遇到的坑(中文乱码详细解释)

QT/C++新手必看:从零搭建学生信息管理系统(附完整代码+避指南) 本文详细介绍了如何使用QT/C++从零开始构建一个高可用的学生信息管理系统,包括项目规划、技术选型、核心类设计、关键功能实现及性能优化技巧。通过完整的代码示例和避指南,帮助新手快速掌握QT/C++开发学生信息管理系统的核心技能,提升开发效率。 阅读详情

本文基于:Qt Creator 4.11.1  Based on Qt 5.14.1 (MSVC 2017, 32 bit) 

1、写入文件编码格式乱码的问题

QString saveFileName = QFileDialog::getSaveFileName(
            this,
            "保存文件",
            QCoreApplication::applicationDirPath(),
            "文本文件 (*.txt)");

if(saveFileName.isEmpty()) return;

QFile qFile(saveFileName);
if(!qFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
      QMessageBox::warning(this, "错误", "文件保存失败!");
      return;
}

QTextStream saveStream(&qFile);
saveStream.setGenerateByteOrderMark(true);  // 写入BOM头
saveStream.setCodec("UTF-8");             // 设置UTF-8编码
saveStream << "123你好";                //出现乱码
qFile.close();

QMessageBox::information(this, "成功", "文件保存成功!");



上面这种直接将字符串"123你好"传递给saveStream,即使设置编码格式和写入BOM头都会出现中文乱码。这个问题还是比较复杂的先来了解几个概念。

源码(mainwindow.cpp)存储编码方式:就是.cpp以哪一种编码方式存储在本地,最常见的就是UTF-8,如上面代码的"123你好"在编译前(也就还是.cpp文件)是以UTF-8存储在计算机里面,以十六进制表示为:31 32 33 e4 bd a0 e5 a5 bd (这是计算机识别的,通过UTF-8解释成 "123你好" 就是我们人看的了)。

编译器解释编码方式:编译器解释也就是可以看作把源文件编译成可执行文件。因为编译器打开文件后看到的也全是一堆二进制,所以同样需要一种编码格式来完成解释工作(这里有一系列工作如把所有字符串放入字符串数据区域),同样常见的编码方式有UTF-8。

运行时环境对编译器解释后的文件处理编码方式:运行编译器解释后的文件,运行环境也有自己的编码方式去处理字符串数据。

总结:所有一个文件从源文件到运行共有三个编码方式,而且还是分离的。说到这里顺便说一下为什么英文和数字就不会出现乱码呢?这是因为标准 ASCII 码对照表的0~127对应关系在任何编码方式(UTF-8、GBK等等)都是一样的,所以无论你的编码方式是如何配置英文数字都不会乱码,除非你自己定义个编码方式!!!!

回到原来问题

        为什么saveStream << "123你好";  会乱码成:123ä½ å¥½,其十六进制为 31 32 33 c3 a4 c2 bd c2 a0 c3 a5 c2 a5 c2 bd 。使用十六进制查看文件可以使用notepad++,其工具栏最右边有一个H图标。这个十六进制明显和UTF-8下的"123你好"的十六进制31 32 33 e4 bd a0 e5 a5 bd,明显不一样,所以是写入时就发生了编码错误,而不是读取文件的时候发生了错误。

            既然是写入时发生错误,可以检查UTF-8编码存储方式下的C字符串在Qt运行时在内存中是不是31 32 33 e4 bd a0 e5 a5 bd,可以运行如下代码:

const char* utf8Str = u8"你好";
QByteArray bytes(utf8Str);
qDebug() << "十六进制是:" << bytes.toHex();

   结果发现在内存中也是 31 32 33 e4 bd a0 e5 a5 bd,因此也就是数据从内存到文件的写入过程中被错误转码,那么也就是说应该是QTextStream或QFile未正确设置UTF-8输出导致的,而不是编译器和运行环境的问题。再进一步排查为了进一步确定是QTextStream还是QFile的问题。不用QTextStream直接用QFile对象进行写入实验,参考代码如下:

        QString saveFileName = QFileDialog::getSaveFileName(
            this,
            "保存文件",
            QCoreApplication::applicationDirPath(),
            "文本文件 (*.txt)");

        if(saveFileName.isEmpty()) return;

        QFile qFile(saveFileName);
        if(!qFile.open(QIODevice::WriteOnly | QIODevice::Truncate )) {
            QMessageBox::warning(this, "错误", "文件保存失败!");
            return;
        }

        qFile.write("123你好");
        qFile.close();

结果是没有出现乱码!!!因此就是QTextStream的问题了,原因可能是QTextStream将const char*视为本地编码(如GBK)。

解决方案:

        1、就是想使用QTextStream和QFile的组合写入文件,首先saveStream.setCodec("UTF-8"); 指定编码方式,第二个是const char*不要行中文,有的话先转为QString再输入到QTextStream对象中,这样也不会乱码。也就是如下两行代码:

saveStream.setCodec("UTF-8"); 
saveStream << QString("123你好");

        2、第二种方式直接使用QFile对象进行文件写入,避免QTextStream的编码。

qFile.write("你好");

2、QStandardItemModel中当读取到item是空项出现程序崩溃

场景如下,目的就是保存下面QStandardItemModel对象的数据:

         QString saveFileName = QFileDialog::getSaveFileName(
            this,
            "保存文件",
            QCoreApplication::applicationDirPath(),
            "文本文件 (*.txt)");

        if(saveFileName.isEmpty()) return;

        QFile qFile(saveFileName);
        if(!qFile.open(QIODevice::WriteOnly | QIODevice::Truncate )) {
            QMessageBox::warning(this, "错误", "文件保存失败!");
            return;
        }
        QTextStream saveStream(&qFile);
        saveStream.setGenerateByteOrderMark(true);  // 写入BOM头
        saveStream.setCodec("UTF-8");             // 设置UTF-8编码

        QString str = "";    //用来做为数据缓冲
        //获取表头数据
        for (int i=0; i<columnCount; ++i) {
            QStandardItem* item = model->horizontalHeaderItem(i);
            str += item->text() + "\t";
        }

        str += "\n";
        //获取每一行数据
        for(int i=0; i<model->rowCount(); ++i){
            for(int j=0; j<columnCount-1 ; ++j){
                QStandardItem* item = model->item(i, j);
                str += item->text() + "\t";
            }
            //婚姻
            if(model->item(i, columnCount-1)->checkState() == Qt::Checked){
                str += QString("是") + "\t";
            }else{
                str += QString("否") + "\t";
            }

            str += "\n";
        }

        saveStream << str;

        qFile.close();

        QMessageBox::information(this, "成功", "文件保存成功!");

对于没有TableView中没有空项的情况下,上面代码用来保存数据是没有问题的。但是一旦出现空项上面代码的运行就会导致程序崩溃,这是因为空item。比如下面我们创建一行,并把一个item数据删除掉,然后点击保存,并使用调试就会看到报出的错误.

进行保存,出现下面报错

表示出现分隔错误,这是因为上面保存代码没有对item有效性进行检查,当item是空项是它就是一个空指针,这时候调用它的Text()方法就会导致程序崩溃。解决方法可以在每次使用item前增加如下代码对其有效性进行检查:

if(!item){
     continue;       //检查是不是空项,是空项就跳过
}

PyQtQStandardItemModel的常见问题解决方法 使用setData()方法向QStandardItemModel中添加数据时,需要注意传入状态,如:Qt.DisplayRole、Qt.EditRole、Qt.ToolTipRole等。对于行列操作,常用的有appendRow()、insertRow()、removeRow()、setHeaderData()等。在PyQt中,QStandardItemModel是一个常用的模型类,它提供了一些便捷方法用于处理数据。在修改数据时,要注意指定要修改的角色,否则修改可能无法生效。 阅读详情

相关推荐

一篇文章带你搞定数学建模中的线性回归模型(05年长江水质问题示例讲解含代码)

文章目录一、问题分析二、原理讲解三、MATLAB 实现线性回归模型 一、问题分析 根据你的预测分析,如果未来10年内每年都要求长江干流的Ⅳ类和Ⅴ类水的比例控制在20%以内,且没有劣Ⅴ类水,那么每年需要处理多少污水 为了达到题目中所要求的水质,可建立废水排放量与各类水百分比之间的二元线性回归模型,对未来十年的废水排放量进行预测,并确定其与各类水所占百分比之间的函数关系式。通过此关系式,可以计算在这种情况下长江所能承受的最大污水排放量,将这个排放量与预测的排放量进行比较,多出来的部分就是需要每年处理掉的。 二、

南淮北安的博客 2148

Qt中文乱码解决

std::cout << QString::fromUtf8("你好").toLocal8Bit().data() << std::endl;

990

论文阅读: SIGIR 2025 ID-Free Not Risk-Free: LLM-Powered Agents Unveil Risks in ID-Free Recommender Syste

咱们平时用的推荐系统(比如购物APP推商品、视频APP推剧),大多是“有ID”的——每个用户、每个商品都有个专属ID,系统靠这些ID记录你的浏览、购买历史,再给你推喜欢的东西。但这种方式有个大问题:新用户、新商品刚上线时没有ID历史数据,系统没法精准推荐,这就是“冷启动”难题。后来人们搞出了“无ID推荐系统”:不用ID了,改成直接分析商品的文字信息(比如商品标题、描述),靠大语言模型(LLM,类似ChatGPT的技术)把文字转成“语义代码”,再通过这些“代码”判断你可能喜欢什么。

CSPhD-winston的博客 947

如何解决 Python 错误 NameError: name ‘X‘ is not defined

当我们在定义类之前访问类时,也会发生该错误。要解决该错误,请将实例化行移至类声明下方。如果我们正在使用来自第三方库的类,则必须先导入该类才能使用它。要解决 Python “我们没有访问不存在的变量。我们不会在声明变量、函数或类之前访问它。我们没有拼错变量、函数或类的名称(名称区分大小写)。我们没有忘记用引号括起一个字符串,例如。我们没有忘记用引号将字典的键括起来。如果不先导入内置模块,就不会使用它们。我们不是从外部访问作用域变量。例如,在函数中声明一个变量并试图从外部访问它。

迹忆客 7万+

Qt解决中文乱码问题

在学习Qt编程的过程中,大多数人都遇到过中文乱码的问题。总结起来有三类: 1.QtCreator中显示的汉字变为乱码,编辑器上方有“Couldnotdecode"..."with"UTF-8"-encoding.Editingnotpossible.”的错误提示。此时,出现乱码的文档是不可编辑的。 2.QtCreator中显示的汉字正常,但编译的时候会出现“常量中有换行符...

weixin_28927079的博客 790

Qt常见中文乱码问题解决方法总结

默认编码错误这种情况是Qt的编码不正确,没有使用UTF-8,但是我觉得大多数人都不是这种,现在Qt在安装之后似乎默认就是UFT-8,若是这种情况,可以参考以下解决方案对默认编码进行一个修改:在Qt上方工具栏中找到 工具-》选项 并单击在更改了编码之后,能解决因为编码无法解析汉字而导致的乱码问题。但是在大多数时候并不是这个情况,下面的情况更常见一点。

m0_73482095的博客 1万+

QT连接Oracle数据库,显示中文乱码的处理方法

最近项目需要,要用QT去连接Oracle数据库,查阅大量资料后最终确定使用QT的oracle驱动QOCI去连接数据库,QT版本5.15.2,VS版本VS2019,oracle服务器版本oracle11g_64位,字符编码格式为AMERICAN_AMERICA.US7ASCII,最终连接上数据库之后,发现中文乱码,显示为一堆问号,尝试过修改环境变量和注册表的方式都无效,历时两周的摸索终于解决现在把解决方案和示例代码一并给出。

suqiangchuan2752的博客 1347

QT QtableView操作详解

本文实现了使用QtableView控件来显示数据数据源使用txt文本作为数据源,使用了QStandardItemModel作为数据模型来实现了对TableView空间的初始化,和对txt数据源的增删改查功能。

断点 7980

QT学习笔记之QT5 + VS2013/VS2015 中文乱码解决办法以及ListView,TableView,TreeView的基本用法...

写在前面 额呵呵呵呵,我又来装逼了,其实也不是很难的一个问题,但是就是记不起来怎么去解决,我还是记录一下吧!(本宝宝智商实在捉急啊!T_T) 解决办法 就在头文件里面加上这句就可以了! #pragma execution_character_set("utf-8") 这个定义无论是在微软的VS还是在QCreator里面都可以解决中文乱码的问题。 这张截图是在Q...

weixin_30321709的博客 754

Qt开发实战指南:从环境配置到部署避的完整解决方案

在跨平台桌面应用开发领域,GUI框架的选择至关重要。Qt作为一款基于C++的成熟框架,其核心机制信号与槽提供了类型安全的对象间通信方式,而元对象系统则支撑了动态特性与内省能力。这些设计使得Qt不仅是一个界面库,更是一个完整的应用框架,具备强大的跨平台能力和模块化架构。在工程实践中,开发者常面临环境配置复杂、依赖管理困难以及部署时动态库缺失等挑战,例如“This application failed to start because no Qt platform plugin could be initial

weixin_33892359的博客 405

Qt数据库应用-文件编码格式识别

在做数据导入导出的过程中,如果应用场景多了,相信各位都会遇到一个问题就是文件编码的问题,有些文件是ANSI编码,有些是utf8编码,有些又是utf8带bom编码,不同的文件编码如果都用同一种编码格式去解析读取出来的数据的话,肯定会遇到乱码的问题,这并不是Qt的问题,也不是什么Qt乱码的问题,而是要识别到文件的编码然后用对应的编码去读取内容,这样就不会出现乱码,当然乱码的出现肯定是中文,如果文件全部是英文数字,无论何种编码,都不会乱码。那么问题来了,如何用程序自动识别文件的编码格式呢?

hw5230的博客 426

Qt5开发及实例——第16章综合实例问题整理(二)

Qt5开发及实例——第16章综合实例问题整理(二) 继续进行第二部分的整理。 7、第16.3.1小节PieView的构造函数参数声明与定义不同同时使用默认参数 在第16.3.1小节,类PieView的构造函数在.h头文件中的声明如下: explicit PieView(QWidget *parent...

woguanshiyinye的博客 524

基于QT与SQLite的学生成绩管理系统:从课程设计到实战开发

在软件开发领域,数据持久化是核心基础概念,指程序运行结束后数据仍能长期保存的技术。其原理是通过文件系统或数据库将内存中的数据写入磁盘等非易失性存储介质。实现数据持久化能确保信息的可靠存储与复用,是各类管理系统的技术基石。常见的实现方案包括文本文件、XML序列化及关系型数据库等,其中SQLite作为轻量级嵌入式数据库,因其零配置、单文件存储特性,在桌面应用和小型项目中备受青睐。结合QT框架的信号与槽机制与模型/视图架构,开发者能高效构建出结构清晰、响应灵敏的图形界面应用。学生成绩管理系统正是融合了数据持久化与

weixin_33971977的博客 439

Qt C++表格控件高效处理Excel文件:从基础原理到股票复盘实战

表格数据处理是现代软件开发中的基础技术需求,其核心原理是通过结构化方式组织和管理二维数据。在C++开发领域,Qt框架提供了QTableWidget和QTableView等强大的表格控件,结合Excel文件读写技术,能够实现高效的数据处理流程。这种技术方案的价值在于将界面展示与数据操作完美结合,解决了传统Excel操作在大型数据集下的性能瓶颈问题。在实际应用场景中,特别是在数据密集型桌面应用、报表生成系统和实时数据监控等工程实践中,Qt C++方案展现出了显著优势。通过合理的架构设计和性能优化,可以轻松处理万

cmff98425的博客 402

Qt QTextStream 输出中文到txt文件乱码

【代码】Qt QTextStream 输出中文到txt文件乱码

huidong_zhu的博客 1001

Qt程序,切换不同地区时出现乱码的解决方法

QLocale切换不同地区乱码的心得

congwang3960的博客 1170

QT中出现的中文乱码问题

最近在学习使用QT,但是过程中碰到了中文乱码的问题,在此将我找到的解决方法共享一下: 1.界面的中文乱码    注释:这里使用字符串没有用tr的。       当我们直接使用以下语句往树组件添加节点时,在显示的时候会出现乱码       QStandardItem *item = new QStandardItem(QString("例子"));      我们可以在主窗口初始化的时候调用

波波诸葛伟 1613

【DeepSeek问答】访问QStandardItemModel::index(r,c)获取的空索引导致程序崩溃

而index(3,6)则指的是第4行第7列的位置,也就是行号比设置的位置少1,列号相同。用户在使用QStandardItemModel的setItem方法时,调用了setItem(4,6,item),也就是在第4行第6列的位置设置了一个item。当尝试通过model的itemFromIndex(index)或者直接访问这个index的数据时,可能会得到一个空指针或者无效的数据,具体取决于调用的方法。总结起来,用户的问题关键在于理解模型中的行号和列号是从0开始计算的,以及未显式设置的item位置默认是空的。

CSUC的博客 1015

曙光I620G10服务器 磁盘驱动程序

本驱动程序可以解决曙光I620G10服务器在安装操作系统过程中无法识别到硬盘的情况,将文件解压后放在U盘中,在安装操作系统选择安装分区时加载此驱动程序,可识别出硬盘。

上一篇: string、const char *、char *的区别和应用
下一篇: QT自定义代理且实现ComboxBox图标加载(个人理解)
崛起的欧巴桑
博客等级 码龄7年 24粉丝 · 6原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值