前言:
- 最近我遇到了一个需要读取本地文件生成json文件的问题,在这里分享下如何在qt中写一个生成json的程序
- 当然也可以使用一些可视化的工具来写json文件(比如:notepad–,还有一些ide都可以),但未免太过于麻烦
- 本文会以一个以qmake搭建的qt项目为例,读取项目中资源的文件,将文件分类生成一个json文件,并选择json文件生成的目录处
首先介绍下会用到的类
一.QDir类(Qt框架中用于处理目录和路径的类)
- QDir的构造函数可以接收路径参数(QString类型),QDir对象指向该路径
QDir(const QString &path = QString())
- 例如像这样使用:
QString resoucePath=":/music/";//像这种加了:的相对路径是已经放入项目中资源部分的文件路径
QDir dir(resoucePath);
- 可以使用
entryList()
方法输出QDir对象指向目录中内容,也就是文件名和子目录,这个也就是我们要写入json文件的数据,读取文件路径存入生成的json里
QStringList QDir::entryList(const QStringList &nameFilters, QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) constQStringList QDir::entryList(QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const
//entryList方法可以不需要写参数,可以看到可以有个重载不需要nameFilters参数,另两个参数都初始化了
-
entryList
方法返回一个QStringList类型,有三个参数,这三个参数分别为:
名称过滤器(nameFilters):根据文件名筛选条目
过滤器(Filters):控制列处哪些类型的条目,也就是文件类型
排序标志(SortFlags):控制条目列表的排序方式 -
过滤器是一个
QDir::Filters
类型的枚举值,可以通过位运算组合多个过滤器使用,常用过滤器:
QDir::Dirs
:只列出目录
QDir::Files
:只列出文件
QDir::NoDotAndDotDot
:不列出.(当前目录)和…(上级目录)
QDir::Hidden
:列出隐藏文件
QDir::NoSymLinks
:不列处符号链接(符号链接就是我们看见的文件的快捷方式)
QDir::Readable
:只列出可读的文件或目录
QDir::Writable
: 只列出可写的文件或目录
QDir::Executable
:只列出可执行的文件或目录
QDir::System
:列出系统文件 -
排序标志是一个QDir::SortFlags类型的枚举值,可以通过位运算组合多个排序标志,常见排序标志:
QDir::Name
:按名称排序(也就是按文件名称字母排序)
QDir::Time
:按修改时间排序
QDir::Size
:按文件大小排序
QDir::Type
:按文件类型排序
QDir::Unsorted
:不排序,按文件系统顺序返回
QDir::IgnoreCase
:忽略大小写排序
QDir::DirsFirst
:目录优于文件
QDir::DirsLast
:目录排在文件之后
QDir::Reversed
:反向排序
qDebug()<<dir.entryList();//输出一遍看下
QStringList filters;//名称过滤器
filters<<"*.mp3";//只获取后缀名为MP3的文件
QStringList files=dir.entryList(filters,QDir::Files);//过滤器只列出文件,排序标志为初始的不排序
输出示例如下:
- 还可以对目录进行管理,例如使用
mkdir()
、rename()
和rmdir()
等方法创建、重命名或删除目录。这些功能以及其他功能就不演示了,毕竟本文没有用上
二.QJsonObject类
-
QJsonObject
类似于map
,以键值对的形式存储数据,其中键是字符串,值可以是QJsonValue
类型(包括字符串,数字,布尔值,数组,对象等)。 -
常用方法:
1.插入数据:
insert(const QString &key,const QJsonValue &value)
:插入一个键值对
2.获取数据:
value(const QString &key) const
:根据键获取值
operator[](const QString &key)
:通过键访问值
3.检查键是否存在:
contains(const QString &key) const
:检查是否包含某个值
4.删除数据:
remove(const QString &key)
:删除指定键的键值对
5.转换为JSON字符串:
使用QJsonDocument
将QJsonObject
转换为JSON字符串
6.从JSON字符串解析:
使用QJsonDocument
将JSON字符串解析为QJsonObject
-
示例:
QJsonObject root;//QJsonObject的的值可以是数组,这个示例存储的值是Json数组QJsonArray manList;QJsonArray womanList;QJsonArray bgmList;QJsonArray endingList;QJsonArray otherList;for(QString& file:files){QString filePath=resoucePath+file;if(file.startsWith("Man_")){//startsWith是用于检查字符串是否以指定的前缀开头manList.append(filePath);}else if(file.startsWith("Woman_")){womanList.append(filePath);}else if(file.startsWith("MusicEx_")){if(file.contains("Win")||file.contains("Lose")){endingList.append(filePath);}else{bgmList.append(filePath);}}else{otherList.append(filePath);}}root["Man"]=manList;//用不同的键分类存入root["Woman"]=womanList;root["BGM"]=bgmList;root["Ending"]=endingList;root["Other"]=otherList;
三.QJsonDocument类
-
可以将QJsonObject和QJsonArray转换为Json文档
-
常用方法:
1.从Json字符串解析:
static QJsonDocument fromJson(const QByteArray &json)
:从Json字符串解析为QJsonDocument
2.从Json二进制数据解析:
static QJsonDocument fromBinaryData(const QByteArray &data)
:从二进制数据解析为QJsonDocument
3.转换为Json字符串:
QByteArray toJson(QJsonDocument::JsonFormat format=Indented)
:将QJsonDocument
转换为Json
字符串
这个方法对于生成的Json字符串格式有着一个枚举类型的参数:
enum JsonFormat{Indented,Compact}
:Indented
是格式化的Json字符串(带缩进),Compact
是紧凑的Json字符串
4.转换为二进制数据:
QByteArray toBinaryData()
:将QJsonDocument
转换为二进制数据
5.获取Json数据:
QJsonObject object() const
:如果文档里包含QJsonObejct
,则返回该对象
QJsonArray array() const
:如果文档里包含QJsonArray
,则返回该数据
6.检查文档类型:
bool isObject() const
:检查文档是否包含QJsonObject
bool isArray() const
:检查文档里是否包含QJsonArray
7.检查文档是否为空:
bool isEmpty() const
:检查文档是否为空
四.QFile类(对文件的操作)
- 打开文件:
bool open(QIODevice::OpenMode mode)
:以指定模式打开文件
常用模式:
QIODevice::ReadOnly
:只读模式
QIODevice:WriteOnly
:只写模式
QIODevice::ReadWrite
:读写模式
QIODevice::Append
:追加模式
QIODevice::Truncate
:清空文件内容 - 关闭文件
void close()
:关闭文件 - 读取文件
QByteArray readAll()
:读取文件所有内容
QByteArray read(qint64 maxSize)
:读取指定大小的内容
QString readLine()
:读取一行内容 - 写入文件
qint64 write(const QByteArray &data)
:写入数据
qint64 write(const char* data,qint64 len)
:写入指定长度的数据 - 文件管理
bool copy(const QString &newName)
:复制文件
bool rename(const QString &newName)
:重命名文件
bool remove()
:删除文件 - 文件信息:
qint64 size()
:获取文件大小
bool exists()
:检查文件是否存在 - 错误处理:
QFile::FileError error()
:获取错误码
QString errorString()
:获取错误信息
关于最终Json文件的生成的目录
-
首先要知道在使用
QFile
类对象创建文件对象时,如果没有指定文件的完整路径,那么该文件会被创建在当前项目工作目录,比如这样创建时:
QFile jsonFile("PlayList.json");
,当前工作目录可以用QDir::currentPath()
获取,返回类型是QString
,
打印:qDebug()<<QDir::currentPath()
-
如果想获取当前应用程序的可执行文件所在的目录的路径,可以使用
QCoreApplication::applicationDirPath()
,返回类型为QString
-
如果你想将文件生成在根目录也就是与.pro同级目录,
在.pro文件添加以下两句:
//定义PRO_DIR为当前.pro文件所在的目录
PRO_DIR = $$PWD
//将PRO_DIR作为宏定义传递给C++代码,\\\"是为了确保PRO_DIR的值
DEFINES += PRO_DIR=\\\"$$PRO_DIR\\\"
完整实例生成Json文件代码:
- 这个例子是写一个类来实现将Json文件生成在项目根目录的,读取项目中资源的文件:
头文件:
#ifndef BGMLIST_H
#define BGMLIST_H#include <QObject>class BGMList : public QObject
{Q_OBJECT
public:explicit BGMList(QObject *parent = nullptr);QString getProjectRootPath();//该函数返回Json生成的目录
signals:
private:
};#endif // BGMLIST_H
#include "bgmlist.h"
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>BGMList::BGMList(QObject *parent): QObject{parent}
{QString resoucePath=":/music/";//像这种加了:的相对路径是已经放入项目中资源部分的文件路径QDir dir(resoucePath);//qDebug()<<dir.entryList();if(!dir.exists()){qDebug()<<"资源路径不存在";return;}qDebug()<<resoucePath;QStringList filters;//名称过滤器filters<<"*.mp3";//只获取后缀名为MP3的文件QStringList files=dir.entryList(filters,QDir::Files);//过滤器只列出文件,排序标志为初始的不排序QJsonObject root;QJsonArray manList;QJsonArray womanList;QJsonArray bgmList;QJsonArray endingList;QJsonArray otherList;for(QString& file:files){QString filePath=resoucePath+file;if(file.startsWith("Man_")){//startsWith是用于检查字符串是否以指定的前缀开头manList.append(filePath);}else if(file.startsWith("Woman_")){womanList.append(filePath);}else if(file.startsWith("MusicEx_")){if(file.contains("Win")||file.contains("Lose")){endingList.append(filePath);}else{bgmList.append(filePath);}}else{otherList.append(filePath);}}root["Man"]=manList;root["Woman"]=womanList;root["BGM"]=bgmList;root["Ending"]=endingList;root["Other"]=otherList;QJsonDocument doc(root);QString projectRootPath=getProjectRootPath()+"/PlayList.json";//Json文件的目录QFile jsonFile("PlayList.json");//qDebug()<<QDir::currentPath();if(jsonFile.open(QIODevice::WriteOnly)){//只写模式jsonFile.write(doc.toJson());jsonFile.close();qDebug()<<"PlayList.json已生成";}else{qDebug()<<"未生成";}
}QString BGMList::getProjectRootPath()
{QString appDir=QCoreApplication::applicationDirPath();//qDebug()<<appDir;QDir dir(appDir);dir.cdUp();//qDebug()<<PRO_DIR;//$$PWD就是.pro文件的目录级别return PRO_DIR;}
- Json文件截图展示: