Qt文件操作

文件基础操作

应用程序中经常需要对设备或者文件进行读取或写入,也经常会对本地文件系统中的文件或者目录进行操作。Qt将这些相关操作的类罗列在一起。
一:输入输出设备
QIODevice类是Qt中所有I/O设备的基础接口类,诸如QFile、QBuffer、QTcpSocket等支持读写数据块的设备提供类一个抽象接口。QIODevice类是抽象的,无法实例化,一般是使用它所定义的接口来提供设备相关的I/O功能。
访问一个设备之前,需要使用open()函数打开该设备,而且必须指定正确的打开模式,QIODevice中所有的打开模式由QIODevice::OpenMode枚举变量定义,其取值如下。

QIODevice::NotOpen		//设备没有打开
QIODevice::ReadOnly		//设备以只读方式打开
QIODevice::WriteOnly	//设备以只写方式打开
QIODevice::ReadWrite	//设备以读写方式打开
QIODevice::Append		//设备以附加模式打开,所有的数据都将写入文件的末尾
QIODevice::Text			//当读取文件时,行结尾终止符会被转化为'\n';当写入时,行结尾终止符会被转化为本地编码。例如在Win32上是'\r\n'
QIODevice::Truncate		//表示每次打开文件后重新录入新内容,文件原有内容将被删除

其中一些值可以使用按位或符号来同时使用,打开设备后可以使用write()或者putChar()来进行写入,使用read()/readLine()或者readAll()进行读取,最后使用close()关闭设备。
QIODevice会区别两种类型的设备:随机存储设备和顺序存储设备。
1、随机存储设备: 随机存储设备支持使用seek()函数来定位到任意的位置,文件当前位置可使用pos()函数来获取,这样的设备有QFile、QBuffer和QTemporaryFile等。
2、顺序存储设备: 顺序存储设备不支持定位到任意位置,数据必须一次性读取,Pos()、size()等函数无法在操作顺序设备时使用,这样的设备有QTcpSocket、QUdpSocket和QProcess等。

QFile file("test.txt");
if(!file.open(QIODevice::ReadWrite | QIODevice::Text)){
	qDebug() << file.errorString();
}
file.write("hello world");
file.seek(0);	//从文件开始偏移0字节
QByteArray array = file.read(11);
file.close();

二:文本流与数据流
QFile类提供类一个用于读/写文件的接口,是一个可以用来读写文本文件、二进制文件和Qt资源的I/O设备。QFile可以单独使用,也可以和QTextStream或者QDataStream一起使用,这样会更方便。
1、文本流方式

QFile file("test.txt");
if(!file.open(QIODevice::ReadWrite | QIODevice::Truncate)){
	qDebug() << file.errorString();
}
ATextStream out(&file);
out << "hello test";		//利用文本流的方式写入内容
file.seek(0);
QTextStream in(&file);
while(!in.atEnd()){
	QString line = in.readLine();	//读取一行字符串
}
file.close();

2、数据流方式

QFile file("test.txt");
if(!file.open(QIODevice::ReadWrite | QIODevice::Text)){
	qDebug() << file.errorString();
}
QDataStream out(&file);
out << "hello test";		//利用文本流的方式写入内容
file.seek(0);
QDataStream in(&file);
QString text;
in >> text;
qDebug() << text;
file.close();

QFileInfo类提供类与系统无关的文件信息,包括文件的名称和在文件系统中的位置(路径),文件的访问权限以及它是否是一个目录或者符号链接文件等,QFileInfo也可以获取文件的大小和最近一次修改/读取的时间等,还可以获取Qt资源的相关信息,QFileInfo可以使用相对或者绝对路径来指向一个文件,可以使用exists()来查看文件是否存在,使用size()可以获取文件大小,文件的类型可以使用isFile()、isDir()和isSymLink()来获取,symLinkTarget()函数可以反悔符号链接指向的文件的名称,可以分别使用path()和fileName()来获取文件路径和文件名,还可以使用baseName()来获取文件名中的基本名称,使用suffix()来获取文件名的后缀,文件的日期可以使用created()、lastModified()和lastRead()来返回,访问权限可以使用isReadable()、isWriteable()和isExecutable()来获取,文件的所有权可以使用owner()、ownerld()、group()、groupID()来获取。

QFileInfo info(file);
qDebug() << info.absoluteFilePath() << endl;	//绝对路径
qDebug() << info.fileName() << endl;			//文件名
qDebug() << info.baseName() << endl;			//基本名称
qDebug() << info.suffix() << endl;				//后缀
qDebug() << info.create() << endl;				//创建时间
qDebug() << info.size() << endl;				//文件大小

QSettings

对于QSettings类在Windows下的两个常见的作用就是读写注册表和配置文件,一般情况下,我们在开发软件过程中需要保存一些配置信息到本地,所以就常会用到QSettings类。

一:注册表操作
一般情况下,我们需要定义一个宏或者常量字符串来指定保存注册表的位置。

#define HKEY_CURRENT_USER_QT "HKEY_CURRENT_USER\\SoftWare\\Digia\\Qt"
或者
const QString HKEY_CURRENT_USER_QT = "HKEY_CURRENT_USER\\SoftWare\\Digia\\Qt";

QCoreApplication::setOrganizationName(QString("Digia"));	//设置组织名
QCoreApplication::setApplicationName(QString("Qt"));		//设置产品名

下面对注册表进行操作

QSettings settings(QSettings::NativeFormat,QSettings::UserScope,
					QCoreApplication::organizationName(),QCoreApplication::applicationName());
settings.setValue("Name", "QtCreator");
settings.setValue("Version", "1.0.0");

若要读取这些信息则可以进行如下操作

QString name = settings.value("Name").toString();
int Version = settings.value("Version").String();

二:操作配置文件
.ini文件,即初始化文件,通常用于对软件参数进行配置和记录,有点是使用方便,嵌入程序也容易,几个接口就够了,很容易掌握。配置文件更小巧,手工配置也更容易,缺点是他的结构只有两层,对于复杂类型数据描述就显得比较无力了。另外ini文件有64kb的大小限制,对于很小的简单配置来说,ini无疑是一种更简练,方便的实现方式。

如果需要对更大及更复杂的数据类型的处理,在Qt中还提供了对xml文件的读写的接口,xml对于描述复杂的数据结构非常的方便,缺点相对ini使用麻烦点,在表达较短的配置时,没有ini简练。而且因为它有比较严格的格式审查机制,容错性也不是特别好,在手写时容易出现错误。抛开配置的功能,作为存储传输数据的手段,xml还有个缺点就是它的处理和存储的效率非常低下,解析速度慢,占用更多存储空间。

1、ini写操作

QString user = ui->usrEdit->text();
QString password = ui->passWordEdit->text();
QSettings *iniWrite = new QSettings("userInfo.ini", QSettings::IniFormat);
QString userkey = tr("/userName/%1").arg(user);
//或者使用iniWrite.beginGroup("userName");
iniWrite->setValue(userkey, password);
this->accept;
delete iniWrite;
iniWrite = nullptr;

2、ini读操作

QSettings *iniRead = new QSettings("userInfo.ini", QSettings::IniFormat);
QStringList userName = iniRead->allkeys();
if(!userName.isEmpty()){
	ui->usrEdit->setText(userName.at(0).split("/").last());
	ui->passWordEdit->setText(iniRead->value(userName.at(0)).toString());
}

Qt还提供了如文件压缩、解压缩等操作接口。

XML与Json

XMl即可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。在电子计算机中,标记值计算机所能理解的信息符合,通过此种标记,计算机之间可以处理包含各种的信息比如文章等。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。是internet环境中跨平台的、依赖于内容的技术,也是当今处理分布式结构信息的有效工具。

QtXml模块提供了一个读写XML文件的流,解析方法包括DOM和SAX,两者的区别是什么呢?
DOM(Document Object Model):将XML文件保存为树的形式,操作简单,便于访问。
SAX(Simple API for XML):提供一个快速的解析器通过一个简单的流API来读取XML文档,它是SAX的替代品,拥有更快更方便的优势。

XML流实例:
需要在.pro文件中添加xml模块(Qt += xml)
头文件 #include
1、创建写入xml文件

void MainWindow::xmlWrite()
{
	QFile xmlFile("test.xml");
	if(!xmlFile.open(QFile::ReadWrite | QFile::Text)){
		qDebug() << "error";
		return;
	}
	QXmlStreamWrite writer(&xmlFile);
	writer.setAutoFormatting(true);		//自动设置xml文件格式
	writer.writeStartDocument();		//自动添加xml说明
	writer.writeStartElement("resp"); 	//添加起始标签元素
	writer.writeAttribute("href","http://www.baidu.com");	//设置始标签元素属性信息
	writer.writeTextElement("city", "ChengDu");		//设置各标签元素及内容
	writer.writeTextElement("windspeed", "2m/s");
	writer.writeTextElement("Temp", "10");
	writer.writeTextElement("humidity", "20%");
	writer.writeEndElement();	//自动结束标签元素
	writer.writeEndDocument();	//表示文档写入完成
	xmlFile.close();
}

2、Xml解析读取

void MainWindow::xmlParse()
{
	QFile xmlFile("test.xml");
	if(!xmlFile.open(QFile::ReadWrite | QFile::Text)){
		qDebug() << "error";
		return;
	}
	QXmlStreamReader reader;
	reader.setDevice(&xmlFile);
	while(!reader.atEnd())
	{
		reader.readNext();	//读取下一个记号并返回记号类型
		if(reader.hasError()){
			qDebug() << "error: " << reader.errorString();
			xmlFile.close();
			return;
		}
		else if(reader.isStartElement())
		{
			if(reader.name() == "city"){
				qDebug() << reader.readElementText();
			}
			if(reader.name() == "humidity"){
				qDebug() << reader.readElementText();
			}
			if(reader.name() == "temp"){
				qDebug() << reader.readElementText();
			}
		}
	}
	xmlFile.close();
}

JSON是一种轻量级的数据交换格式,它是基于javaScript的一个子集,JSON采用完全独立于语言的文本格式,但是也使用流类似于C语言家族的习惯(包括C、C++、C#、java、javaScript、Perl、Python等)。这些特性是JSON成为理想的数据交换语言,易于人阅读和编写,同时也易于机器解析和生成。
Qt5中JSON的生成与解析

QJsonDocument既可以从一个基于文本表示的UTF-8编码,又可以从Qt自己的二进制格式读取和写入这个文件。

JSON文档可以从它的基于文本的表示使用QJsonDocument::fromJson()转换为QJsonDocument,用toJSON()将其转换回文字,解析器非常快速和高效,将JSON转换为二进制表示。

QJsonObject类用于封装JSON对象,JSON对象是键值对,其中键是唯一的字符串,其值由QJsonValue代表,一个QJsonObject可以从QVariantMap转换/被转换。

QJsonArray类用于封装JSON数组,一个JSON数组列表值,该列表可以通过从阵列插入和移除QJsonValue的操作,一个QJsonArray可以从QVariantList转换/被转换。

QJsonDocument有效解析后的文档可以使用!iSNull()判断,使用isArray()和isObject()来判断是否包含一个数组或对象,文档中包含的数组或对象可以使用array()或object()进行检索,然后读取或操纵。

实例:
1、Qt中Json文件的创建和写入

void MainWindow::jsonWrite()
{
	QFile jsonFile("test.json");
	if(!jsonFile.open(QFile::ReadWrite | QFile::Text)){
		qDebug() << "error";
		return;
	}
	QJsonObject json1;		//封装json对象
	json1.insert("city", "ChengDu");
	json1.insert("weather", "cold");
	QJsonArray jsarray;		//封装json数组
	jsarray.insert(0,json1);
	QJsonObject json;
	json.insert("data", jsarray);
	json.insert("status", "test");
	QJsonDocument document;		//读写json文档使用
	document.setObject(json);
	QByteArray jsonData;
	jsonData.append(document.toJson(QJsonDocument::Compact));	//Compact表示按json格式
	QTextStream in(&jsonFile);
	jsonFile.close();
}

2、Qt中Json文件的解析

void MainWindow::jsonParse()
{
	QFile jsonFile("test.json");
	if(!jsonFile.open(QFile::ReadWrite | QFile::Text)){
		qDebug() << "error";
		return;
	}
	QByteArray byte_array = jsonFile.readAll();
	QJsonParsseError json_error;
	QJsonDocument parse_doucment = QJsonDocument::fromJson(byte_array, &json_error);
	if(json_error == QJsonParseError::NoError)
	{
		QJsonObject obj = parse_doucment.object();	//解析json对象
		QJsonValue desc = obj.take("desc");
		if(desc.toString() != "OK")
		{
			qDebug() << "error\n";
			return;
		}
		QJsonValue data = obj.take("data");
		qDebug() << data.toObject().take("health").toString();
		QJsonValue forecastvalue = data.toObject().take("forecast");
		QJsonArray forecast = forecastvalue.toArray();
		for(int i = 0; i < 5; i++)
		{
			QJsonValue value = forecast.at(i);
			QJsonObject object = value.toObject();
			qDebug() << object.take("winddirection").toString();
			qDebug() << object.take("date").toString();
			qDebug() << object.take("windspeed").toString();
			qDebug() << object.take("high").toString();
			qDebug() << object.take("low").toString();
			qDebug() << object.take("type").toString();
		}
	}
	else
	{
		qDebug() << "Jsonerror";
		return;
	}
	jsonFile.close();
}

本文章算是作为我个人的学习记录方便后面复习,欢迎大家指正错误。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值