1 简介
参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=45
参考文档:《Qt教程.docx》
说明:本文主要介绍Qt的文件系统。
2 知识点
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 传输数据;
3 基本文件操作
QFile提供了从文件中读取和写入数据的能力。
我们通常会将文件路径作为参数传给QFile的构造函数。不过也可以在创建好对象最后,使用setFileName()来修改。
QFile主要提供了有关文件的各种操作,比如打开文件、关闭文件、刷新文件等。我们可以使用QDataStream或QTextStream类来读写文件,也可以使用QIODevice类提供的read()、readLine()、readAll()以及write()这样的函数。
值得注意的是,有关文件本身的信息,比如文件名、文件所在目录的名字等,则是通过QFileInfo获取,而不是自己分析文件路径字符串。
4 测试
(1)打开、读取、写入文件
功能:创建两个按钮,“read file”按钮打开一个文本框,读取文件的内容到textEdit;“save file”按钮将textEdit中的内容保存到一个文件中。界面如下:
读取文件使用到的函数和步骤:
1)创建一个文件对象:QFilefile(path);
2)以只读方式打开文件:boolisOk=file.open(QIODevice::ReadOnly);
3)读取文件的内容有多种方式,这里介绍两种:
一次性读取文件全部内容:QByteArrayarray=file.readAll();
一次只读取一行:
1 QByteArray array;
2 while (file.atEnd() == false) {
3 //读一行
4 array += file.readLine();
5 }
4)关闭文件:file.close();
写入文件用到的函数和步骤:
1)创建文件对象:QFile file;
2)关联文件名字:file.setFileName(path);
3)以只写方式打开文件:bool isOK = file.open(QIODevice::WriteOnly);
4)向文件中写入内容:file.write(str);
5)关闭文件:file.close();
完整代码:

1 #include "widget.h"
2 #include "ui_widget.h"
3 #include <QFile>
4 #include <QFileDialog>
5 #include <QByteArray>
6 #include <QByteArray>
7
8 Widget::Widget(QWidget *parent) : 9 QWidget(parent), 10 ui(new Ui::Widget) 11 { 12 ui->setupUi(this); 13 } 14
15 Widget::~Widget() 16 { 17 delete ui; 18 } 19
20 void Widget::on_pushButton_read_clicked() 21 { 22 QString path = QFileDialog::getOpenFileName(this, "open", "../", "TXT(*.txt)"); 23 if (path.isEmpty() == false) { 24 QFile file(path); //文件对象
25 bool isOK = file.open(QIODevice::ReadOnly); //打开文件
26 if (true == isOK) { 27 //一行一行读取文件
28 QByteArray array; 29 while (file.atEnd() == false) { 30 array += file.readLine(); 31 } 32 ui->textEdit->setText(array); 33 file.close(); 34 } 35 } 36 } 37
38 void Widget::on_pushButton_save_clicked() 39 { 40 QString path = QFileDialog::getOpenFileName(this, "open", "../", "TXT(*.txt)"); 41 if (path.isEmpty() == false) { 42 QFile file(path); //文件对象
43 bool isOK = file.open(QIODevice::WriteOnly); //打开文件
44 if (true == isOK) { 45 //获取文本编辑区的内容
46 QString str = ui->textEdit->toPlainText(); 47 //转换为本地编码写入
48 file.write(str.toLocal8Bit()); 49 file.close(); 50 } 51 } 52 }
运行测试:
上述代码中,打开文件使用的是系统默认的编码格式:UTF-8,如果打开其它编码格式的文件就会乱码。
(2)获取文件信息
比如获取文件的名字、文件后缀、文件大小、文件创建时间等信息。
通过QFileInfo类来实现的。这个很简单,直接给出测试代码:

1 Widget::Widget(QWidget *parent) : 2 QWidget(parent), 3 ui(new Ui::Widget) 4 { 5 ui->setupUi(this); 6
7 QFileInfo info("../demo.txt"); 8 qDebug() << "文件名字" << info.fileName().toUtf8().data(); 9 qDebug() << "文件后缀" << info.suffix(); 10 qDebug() << "文件大小" << info.size(); 11 qDebug() << "文件创建时间" << info.created().toString("yyyy-MM-dd hh:mm:ss"); 12 qDebug() << "文件路径" << info.filePath(); 13 }
(3)QDataStream读写文件
QDataStream提供了基于QIODevice的二进制数据的序列化。数据流是一种二进制流,这种流完全不依赖于底层操作系统、CPU 或者字节顺序(大端或小端)。
QDataStream既能够存取 C++ 基本类型,如 int、char、short 等,也可以存取复杂的数据类型,例如自定义的类。实际上,QDataStream对于类的存储,是将复杂的类分割为很多基本单元实现的。
测试代码:创建两个函数,writeData()写文件,readData()读文件。

1 #include "widget.h"
2 #include "ui_widget.h"
3 #include <QDataStream>
4 #include <QFile>
5 #include <QDebug>
6
7 #define cout qDebug() << "[" << __FILE__ <<":" << __LINE__ << "]"
8
9
10 Widget::Widget(QWidget *parent) : 11 QWidget(parent), 12 ui(new Ui::Widget) 13 { 14 ui->setupUi(this); 15
16 writeData(); 17 readData(); 18 } 19
20 Widget::~Widget() 21 { 22 delete ui; 23 } 24
25 void Widget::writeData() 26 { 27 //创建文件对象
28 QFile file("../text.txt"); 29 //打开文件,只写方式
30 bool isOK = file.open(QIODevice::WriteOnly); 31 if (true == isOK) { 32 //创建数据流,和file文件关联 33 //往数据流中写数据,相当于往文件里写数据(二进制)
34 QDataStream stream(&file); 35 stream << QString("主要看气质") << 250; 36 file.close(); 37 } 38 } 39
40 void Widget::readData() 41 { 42 //创建文件对象
43 QFile file("../text.txt"); 44 //打开文件,只读方式
45 bool isOK = file.open(QIODevice::ReadOnly); 46 if (true == isOK) { 47 //创建数据流,和file文件关联 48 //从数据流中读数据,相当于从文件里读数据(二进制)
49 QDataStream stream(&file); 50 //读的时候,按写的顺序取数据
51 QString str; 52 int a; 53 stream >> str >> a; 54 cout << str << a; 55 file.close(); 56 } 57 }
运行测试:
打印输出:[ ..\file_2\widget.cpp : 54 ] "主要看气质" 250
我们打开text.txt文件,会看到是乱码的,因为是二进制文件。
(4)QTextStream读写文件
QTextStream是操作纯文本文件的。QTextStream会自动将 Unicode 编码同操作系统的编码进行转换,这一操作对开发人员是透明的。它也会将换行符进行转换,同样不需要自己处理。
QTextStream使用 16 位的QChar作为基础的数据存储单位,同样,它也支持 C++ 标准类型,如 int 等。实际上,这是将这种标准类型与字符串进行了相互转换。
测试代码:

1 #include "widget.h"
2 #include "ui_widget.h"
3 #include <QFile>
4 #include <QTextStream>
5 #include <QDebug>
6 #include <QFileDialog>
7
8 #define cout qDebug() << "[" << __FILE__ <<":" << __LINE__ << "]"
9
10 Widget::Widget(QWidget *parent) : 11 QWidget(parent), 12 ui(new Ui::Widget) 13 { 14 ui->setupUi(this); 15
16 writeData(); 17 readData(); 18 } 19
20 Widget::~Widget() 21 { 22 delete ui; 23 } 24
25 void Widget::writeData() 26 { 27 QFile file; 28 file.setFileName("../demo.txt"); 29 bool isOK = file.open(QIODevice::WriteOnly); 30 if (true == isOK) { 31 QTextStream stream(&file); 32 //指定编码
33 stream.setCodec("UTF-8"); 34 stream << QString("主要看气质") << 250; 35 file.close(); 36 } 37 } 38
39 void Widget::readData() 40 { 41 QFile file; 42 file.setFileName("../demo.txt"); 43 bool isOK = file.open(QIODevice::ReadOnly); 44 if (true == isOK) { 45 QTextStream stream(&file); 46 stream.setCodec("UTF-8"); 47 //读取出来的就是字符串
48 QString str = stream.readAll(); 49 cout << str; 50 file.close(); 51 } 52 }
运行测试:
打印输出:[ ..\file_3\widget.cpp : 53 ] "主要看气质250"
打开demo.txt文件,可以发现文件是可读的,不会乱码。
(5)QBuffer读写文件
QBuffer创建的是内存文件。
直接给出测试代码:

1 Widget::Widget(QWidget *parent) : 2 QWidget(parent), 3 ui(new Ui::Widget) 4 { 5 ui->setupUi(this); 6 7 //创建内存文件 8 QByteArray array; 9 QBuffer memfile(&array); 10 memfile.open(QIODevice::WriteOnly); 11 memfile.write("111111111111"); 12 memfile.write("222222222222"); 13 memfile.close(); 14 qDebug() << memfile.buffer(); 15 qDebug() << "array" << array; 16 17 QBuffer memfile1; 18 QDataStream stream(&memfile1); 19 memfile1.open(QIODevice::WriteOnly); 20 stream << QString("测试") << 250; 21 memfile1.close(); 22 23 memfile1.open(QIODevice::ReadOnly); 24 QDataStream in; 25 in.setDevice(&memfile1); 26 QString str; 27 int a; 28 in >> str >> a; 29 memfile1.close(); 30 qDebug() << str.toUtf8().data() << a; 31 }