实例功能概述
文本文件是指以以纯文本格式存储的文件,例如用 Qt Creator 编写的 C++ 程序的头文件和源文件。HTML 和 XML 文件也是纯文本文件,只是读取之后需要对内容进行解析之后再显示。
Qt 提供了两种读写纯文本文件的基本方法,一种是用 QFile
类的 QIODevice
读写功能直接进行读写,另一种是利用 QFile
和 QTextStream
结合起来,用流(Stream)的方法进行文件读写。
我编写了一个例子来展示这两种方法读写文本文件的效果,现在运行结果:
QFile 读写文本
文件读取
QFile 类是直接和 IO 设备打交道的,进行文件读写操作的类,使用 QFile 可以直接打开或保存文本文件。图中“QFile 直接打开“按钮用 QFile 类的功能直接打开文本文件,按钮的槽函数及相关函数代码如下:
void MainWindow::on_actOpen_IODevice_triggered()
{//打开文件
QString curPath=QDir::currentPath();//获取系统当前目录
QString dlgTitle="打开一个文件"; //对话框标题
QString filter="程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)"; //文件过滤器
QString aFileName=QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter);
if (aFileName.isEmpty())
return;
openTextByIODevice(aFileName);
}
bool MainWindow::openTextByIODevice(const QString &aFileName)
{//用IODevice方式打开文本文件
QFile aFile(aFileName);
// aFile.setFileName(aFileName);
if (!aFile.exists()) //文件不存在
return false;
if (!aFile.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
ui->textEditDevice->setPlainText(aFile.readAll());
aFile.close();
ui->tabWidget->setCurrentIndex(0);
return true;
}
自定义函数 openTextByIODevice()
实现文本打开功能。定义了 QFile 对象变量 aFile 时将文件名传递给他,检查文件存在后,通过 open()
函数打开文件;注意,QFile::open()
函数打开文件时需要传递 QIODevice::OpenModeFlag
枚举类型的参数,决定文件以什么方式打开,主要有以下取值:
取值 | 作用 |
---|---|
QIODevice::ReadOnly | 只读打开,用于载入文件 |
QIODevice::WriteOnly | 只写打开,用于保存文件 |
QIODevice::ReadWrite | 读写打开 |
QIODevice::Append | 添加模式打开,新写入的文件添加到文件尾部 |
QIODevice::Truncate | 截取方式打开,文件原有内容被删除 |
QIODevice::Text | 文本方式打开,读取时“\n”被自动翻译为换行符,串结束符会自动翻译为系统平台编码,如 Windows 平台下是“\r\n” |
文件写入
“QFile”另存为按钮用 QFile 类的功能将 QPlaintextEdit 组件中的文本保存为一个文本文件,实现代码如下:
void MainWindow::on_actSave_IODevice_triggered()
{
QString curPath=QDir::currentPath();//获取系统当前目录
QString dlgTitle="另存为一个文件"; //对话框标题
QString filter="h文件(*.h);;c++文件(*.cpp);;文本文件(*.txt);;所有文件(*.*)"; //文件过滤器
QString aFileName=QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
if (aFileName.isEmpty())
return;
saveTextByIODevice(aFileName);
}
bool MainWindow::saveTextByIODevice(const QString &aFileName)
{ //用IODevice方式保存文本文件
QFile aFile(aFileName);
// aFile.setFileName(aFileName);
if (!aFile.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
QString str=ui->textEditDevice->toPlainText();//整个内容作为字符串
QByteArray strBytes=str.toUtf8();//转换为字节数组
// QByteArray strBytes=str.toLocal8Bit();
aFile.write(strBytes,strBytes.length()); //写入文件
aFile.close();
ui->tabWidget->setCurrentIndex(0);
return true;
}
自定义函数 saveTextByIODevice()
实现文件保存功能,为了保存文件,用 open() 打开文件时,使用的模式是 QIODevice::WriteOnly | QIODevice::Text
。使用 WriteOnly 隐含着 Truncate,即删除文件原有内容。
首先将 QPlaintextEdit 组件上的文本导出为字符串,将 QString 类的 toUtf8()
函数转化为 UTF8 编码的字节数组,然后调用 QFile::write()
函数将字节数组内容写入文件。
QFile 和 QTextStream 结合读写文本文件
QTextStream 与 IO 读写设备结合,为数据读写提供了一些方便的方法类,QTextStream 可以与 QFile、QTemporaryFile、QBuffer、QTcpSocket 和 QUdpSocket 等 IO 设备类结合使用。
这里我们将 QFile 和 QTextStream 结合,读取文本文件的自定义函数 openTextByStream()
的代码如下:
bool MainWindow::openTextByStream(const QString &aFileName)
{ //用 QTextStream打开文本文件
QFile aFile(aFileName);
if (!aFile.exists()) //文件不存在
return false;
if (!aFile.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QTextStream aStream(&aFile); //用文本流读取文件
// aStream.setAutoDetectUnicode(true); //自动检测Unicode,才能正常显示文档内的汉字
ui->textEditStream->setPlainText(aStream.readAll());
aFile.close();//关闭文件
ui->tabWidget->setCurrentIndex(1);
return true;
}
在创建 QTextStream 实例时传递一个 QFile 参数,这样,QFile 对象和 QTextStream 对象就结合在一起了,利用 QTextStream 可读写文件。如果文本文件里有汉字,需要设定为自动识别 Unicode 码,即调用 setAutoDetectUnicode(true)
函数。
上面的代码中使用了 QTextStream::readAll()
来一次性读取所有内容。但是 QTextStream
提供了一些其他方便使用的接口函数,如使用 QTextStream::readLine()
可以逐行读取文本,这种方式适合用于需要逐行解析字符串内容的使用场景:
bool MainWindow::openTextByStream(const QString &aFileName)
{ //用 QTextStream打开文本文件
QFile aFile(aFileName);
if (!aFile.exists()) //文件不存在
return false;
if (!aFile.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QTextStream aStream(&aFile); //用文本流读取文件
// aStream.setAutoDetectUnicode(true); //自动检测Unicode,才能正常显示文档内的汉字
ui->textEditStream->clear();//清空
while (!aStream.atEnd())
{
str=aStream.readLine();//读取文件的一行
ui->textEditStream->appendPlainText(str); //添加到文本框显示
}
aFile.close();//关闭文件
ui->tabWidget->setCurrentIndex(1);
return true;
}
saveTextByStream()
使用 QTextStream 保存文件的自定义函数,代码如下:
bool MainWindow::saveTextByStream(const QString &aFileName)
{//用QTextStream保存文本文件
QFile aFile(aFileName);
if (!aFile.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
QTextStream aStream(&aFile); //用文本流读取文件
// aStream.setAutoDetectUnicode(true); //自动检测Unicode,才能正常显示文档内的汉字
QString str=ui->textEditStream->toPlainText(); //转换为字符串
aStream<<str; //写入文本流
aFile.close();//关闭文件
return true;
}
解决中文乱码问题
在使用 QTextStream 读写有中文内容的文本文件时,为了能正确识别 Unicode 码,需要调用 setAutoDetectUnicode(true)
,设置 QTextStream 可以自动识别 Unicode 码,如果不做次设置,读取文件中的中文将是乱码,无法正常显示。
为了解决 Unicode 的识别问题,可以在应用程序中作全局设置,使应用程序支持 Unicode。方法是在 main 函数中使用 QTextCodec 类进行编码设置。例如:
int main(int argc, char *argv[])
{
//解决汉字乱码问题
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec); //解决汉字乱码问题
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
这样应用程序就有了对 Unicode 码的支持,即使在使用 QTextStream 时没有设置识别 Unicode 码,也可以显示汉字。