Qt 5——文件系统操作

简介: Qt 5——文件系统操作

文件系统


文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库,提供了跨平台的文件操作能力。Qt 通过QIODevice提供了对 I/O 设备的抽象,这些设备具有读写字节块的能力。下面是 I/O 设备的类图(Qt5):



QIODevice:所有 I/O 设备类的父类,提供了字节块读写的通用操作以及基本接口;


QFileDevice:Qt5新增加的类,提供了有关文件操作的通用实现。


QFlie:访问本地文件或者嵌入资源;


QTemporaryFile:创建和访问本地文件系统的临时文件;


QBuffer:读写QbyteArray, 内存文件;


QProcess:运行外部程序,处理进程间通讯;


QAbstractSocket:所有套接字类的父类;


QTcpSocket:TCP协议网络数据传输;


QUdpSocket:传输 UDP 报文;


QSslSocket:使用 SSL/TLS 传输数据;


1 基本文件操作


QFile提供了从文件中读取和写入数据的能力。


我们通常会将文件路径作为参数传给QFile的构造函数。不过也可以在创建好对象最后,使用setFileName()来修改。


QFile需要使用 / 作为文件分隔符,不过,它会自动将其转换成操作系统所需要的形式。例如 C:/windows 这样的路径在 Windows 平台下同样是可以的。


QFile主要提供了有关文件的各种操作,比如打开文件、关闭文件、刷新文件等。我们可以使用QDataStream或QTextStream类来读写文件,也可以使用QIODevice类提供的read()、readLine()、readAll()以及write()这样的函数。值得注意的是,有关文件本身的信息,比如文件名、文件所在目录的名字等,则是通过QFileInfo获取,而不是自己分析文件路径字符串。


下面我们使用一段代码来看看QFile的有关操作:


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QFile file("in.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Open file failed.";
        return -1;
    } else {
        while (!file.atEnd()) {
            qDebug() << file.readLine();
        }
    }
    QFileInfo info(file);
    qDebug() << info.isDir();
    qDebug() << info.isExecutable();
    qDebug() << info.baseName();
    qDebug() << info.completeBaseName();
    qDebug() << info.suffix();
    qDebug() << info.completeSuffix();
    return app.exec();
}


我们首先使用QFile创建了一个文件对象。


  1. 这个文件名字是 in.txt。如果你不知道应该把它放在哪里,可以使用QDir::currentPath()来获得应用程序执行时的当前路径。只要将这个文件放在与当前路径一致的目录下即可。


  1. 使用open()函数打开这个文件,打开形式是只读方式,文本格式。


这个类似于fopen()的 r 这样的参数。open()函数返回一个 bool 类型,如果打开失败,我们在控制台输出一段提示然后程序退出。否则,我们利用 while 循环,将每一行读到的内容输出。


  1. 可以使用QFileInfo获取有关该文件的信息。


QFileInfo有很多类型的函数,我们只举出一些例子。比如:


  1. isDir()检查该文件是否是目录;


  1. isExecutable() 检查该文件是否是可执行文件等。


  1. baseName() 可以直接获得文件名;


  1. completeBaseName() 获取完整的文件名


  1. suffix() 则直接获取文件后缀名。


  1. completeSuffix() 获取完整的文件后缀


我们可以由下面的示例看到,baseName()和completeBaseName(),以及suffix()和completeSuffix()的区别:


QFileInfo fi("/tmp/archive.tar.gz");
QString base  = fi.baseName();  // base = "archive"
QString base  = fi.completeBaseName();  // base = "archive.tar"
QString ext   = fi.suffix();  // ext = "gz"
QString ext   = fi.completeSuffix();  // ext = "tar.gz"


2 二进制文件读写


我们可以直接读写没有编码的二进制数据,例如图像、视频、音频等。


QDataStream既能够存取 C++ 基本类型,如 int、char、short 等,也可以存取复杂的数据类型,例如自定义的类。实际上,QDataStream对于类的存储,是将复杂的类分割为很多基本单元实现的。


结合QIODevice,QDataStream可以很方便地对文件、网络套接字等进行读写操作。我们从代码开始看起:


QFile file("file.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
out << QString("the answer is");
out << (qint32)42;


如果你直接运行这段代码,你会得到一个空白的 file.dat,并没有写入任何数据。这是因为我们的file没有正常关闭。为性能起见,数据只有在文件关闭时才会真正写入。因此,我们必须在最后添加一行代码:


file.close(); // 如果不想关闭文件,可以使用 file.flush();


接下来我们将存储到文件中的答案取出来


QFile file("file.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file);
QString str;
qint32 a;
in >> str >> a;

唯一需要注意的是,你必须按照写入的顺序,将数据读取出来。顺序颠倒的话,程序行为是不确定的,严重时会直接造成程序崩溃。


QDataStream同QIODevice有什么区别?


区别在于,QDataStream提供流的形式,性能上一般比直接调用原始 API 更好一些。


3 文本文件读写


QTextStream使用 16 位的QChar作为基础的数据存储单位,同样,它也支持 C++ 标准类型,如 int 等。实际上,这是将这种标准类型与字符串进行了相互转换。


QTextStream同QDataStream的使用基本一致,例如下面的代码将把“The answer is 42”写入到 file.txt 文件中:


QFile data("file.txt");
if (data.open(QFile::WriteOnly | QIODevice::Truncate)) 
{
    QTextStream out(&data);
    out << "The answer is " << 42;
}


这里,我们在open()函数中增加了QIODevice::Truncate打开方式。我们可以从下表中看到这些打开方式的区别:



QTextStream与QDataStream注意


虽然QTextStream的写入内容与QDataStream一致,但是读取时却会有些困难:


QFile data("file.txt");
if (data.open(QFile::ReadOnly)) 
{
    QTextStream in(&data);
    QString str;
    int ans = 0;
    in >> str >> ans;
}


在使用QDataStream的时候,这样的代码很方便,但是使用了QTextStream时却有所不同:读出的时候,str 里面将是 The answer is 42,ans 是 0。这是因为当使用QDataStream写入的时候,实际上会在要写入的内容前面,额外添加一个这段内容的长度值。而以文本形式写入数据,是没有数据之间的分隔的。因此,使用文本文件时,很少会将其分割开来读取,而是使用诸如使用:


QTextStream::readLine() 读取一行


QTextStream::readAll()读取所有文本


这种函数之后再对获得的QString对象进行处理。


默认情况下,QTextStream的编码格式是 Unicode,如果我们需要使用另外的编码,可以使用:


stream.setCodec("UTF-8");


这样的函数进行设置。


Qt 工程案例


#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QFile>
#include <QTextCodec>
#include <QFileInfo>
#include <QDebug>
#include <QDateTime>
#include <QTextStream>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //点击按钮 选取文件
    connect(ui->pushButton,&QPushButton::clicked,[=](){
         QString path = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\zhangtao\\Desktop");
         if(path.isEmpty())
         {
            QMessageBox::warning(this,"警告","打开失败");
         }
         else
         {
             //将路径 放入到lineEdit
             ui->lineEdit->setText(path);
             //读取文件
             //QFile默认支持UTF-8格式
             //QTextCodec * codec = QTextCodec::codecForName("gbk");
             QFile file(path); //参数路径名称
             //指定打开方式(只读)
             //file.open(QIODevice::ReadOnly);
             file.open(QFileDevice::ReadOnly);
             QByteArray array;
             array = file.readAll();
//             while( !file.atEnd())
//             {
//               array += file.readLine();
//             }
             //设置到 文本编辑框中
             ui->textEdit->setText(array);
             file.close();
             //读gbk
             // ui->textEdit->setText( codec->toUnicode(array));
             //写文件
             //重新指定打开方式
//             file.open(QFileDevice::Append);
//             file.write("哦哦哦哦哦哦");
//             file.close();
             //通过QFileInfo读取文件信息
               QFileInfo info(path);
               qDebug() << "路径: "<< info.filePath() << " 名称: "
                        <<info.fileName() << " 文件大小" << info.size() << "后缀名:"<<info.suffix();
               qDebug() << "创建日期:" <<info.created().toString("yyyy-MM-dd hh:mm:ss");
               qDebug() << "修改日期:" <<info.lastModified().toString("yyyy/MM/dd hh:mm:ss");
         }
    });
    //文件流读写文件
    //分类:文本流(基础数据类型) 和 数据流 (大型QImage)
    //文本流
//    QFile file("aaa.txt");
//    file.open(QFileDevice::WriteOnly);
//    QTextStream stream(&file);
//    stream<< QString("hello World") << 123456 ;
//    file.close();
//    //读取
//    file.open(QFileDevice::ReadOnly);
//    QString str;
//    //stream >>str; //读取空格 结束
//    str = stream.readAll();
//    qDebug() << str;
    //数据流 二进制
    QFile file("bbb.txt");
    file.open(QFileDevice::WriteOnly);
    QDataStream stream(&file);
    stream << QString("hello World") << 123456;
    file.close();
    //读数据
    file.open(QFileDevice::ReadOnly);
    QString str;
    int num;
    stream >>str >> num;
    qDebug() << str << num;
}
Widget::~Widget()
{
    delete ui;
}
相关文章
|
4月前
|
编译器
QT creator开发环境下 界面更改后运行程序不能实时更新或者在源文件添加该控件后无法编译的问题
在使用QT Creator开发界面的过程中,偶尔会出现添加控件后,运行程序后,界面控件无法更新的情况,或者在源文件使用该控件却出现无法编译的情况,使用QT Creator 4.8.2也会出现这个情况,也不知道这种情况会不会在以后有所改善。
68 0
|
5月前
|
存储 API Windows
8.3 Windows驱动开发:内核遍历文件或目录
在笔者前一篇文章`《内核文件读写系列函数》`简单的介绍了内核中如何对文件进行基本的读写操作,本章我们将实现内核下遍历文件或目录这一功能,该功能的实现需要依赖于`ZwQueryDirectoryFile`这个内核API函数来实现,该函数可返回给定文件句柄指定的目录中文件的各种信息,此类信息会保存在`PFILE_BOTH_DIR_INFORMATION`结构下,通过遍历该目录即可获取到文件的详细参数,如下将具体分析并实现遍历目录功能。
51 0
8.3 Windows驱动开发:内核遍历文件或目录
|
6月前
|
网络协议 网络安全
30 QT - 文件系统概述
30 QT - 文件系统概述
20 0
|
11月前
|
C++
VS2019 + Qt5.12 配置完成后,无法打开 Qt 源文件解决方案(非常实用)
VS2019 + Qt5.12 配置完成后,无法打开 Qt 源文件解决方案(非常实用)
|
Linux 5G 开发工具
图形界面下,如何查看LINUX隐藏的文件、目录
图形界面下,如何查看LINUX隐藏的文件、目录
82 0
|
Linux 编译器 Shell
Linux系统下实现QT程序打包发布
Linux系统下实现QT程序打包发布
1440 0
|
XML C语言 数据格式
CentOS8安装Geant4笔记(三):Geant4介绍、编译、安装支持Qt5界面并运行exampleB1例程显示Qt界面
CentOS8安装Geant4笔记(三):Geant4介绍、编译、安装支持Qt5界面并运行exampleB1例程显示Qt界面
CentOS8安装Geant4笔记(三):Geant4介绍、编译、安装支持Qt5界面并运行exampleB1例程显示Qt界面
|
计算机视觉
Qt实用技巧:设置应用程序exe的图标
Qt实用技巧:设置应用程序exe的图标
Qt实用技巧:设置应用程序exe的图标
|
Linux
【Linux】多窗口功能(对比同一个文件)
【Linux】多窗口功能(对比同一个文件)
108 0
【Linux】多窗口功能(对比同一个文件)

推荐镜像

更多