Qt文本读写之一:输入输出设备和文件操作

一、输入输出设备

QIODevice类是Qt中所有I/O设备的基础接口类,为诸如QFile、QBuffer和 QTcpSocket等支持读/写数据块的设备提供了一个抽象接口。QIODevice类是抽象的,无法被实例化,一般是使用它所定义的接口来提供设备无关的I/O功能。

QIODevice类的继承关系图

QIODevice会区别两种类型的设备:随机存取设备和顺序存储设备。(可以在程序中使用isSequentiaU)函数来判断设备的类型。)

随机存取设备支持使用seek)函数来定位到任意的位置。文件中的当前位置可以使用pos)函数来获取。这样的设备有QFile、QBuffer等。
顺序存储设备不支持定位到任意的位置,数据必须一次性读取。Pos)和size) 等函数无法在操作顺序设备时使用。这样的设备有QTcpSocket、QUdpSocket 和QProcess等。

文件打开模式

访问一个设备以前,需要使用open)函数打开该设备,而且必须指定正确的打开模式。QIODevice中所有的打开模式由QIODevice::OPenMode枚举变量定义,其取值如下表所列,其中的一些值可以使用按位或符号“丨”来同时使用。打开设备后可以使用write)或者putChar)来进行写人,使用read)、readLine)或者readAll)进行读取,最后使用close)关闭设备。

枚举值 描述
QIODevice::NotOpen 未打开
QIODevice::ReadOnly 以只读方式打开
QIODevice::WriteOnly 以只写方式打开
QIODevice::ReadWrite 以读写方式打开
QIODevice::Append 以追加的方式打开,新增加的内容将被追加到文件末尾
QIODevice::Truncate 以重写的方式打开,在写入新的数据时会将游标设置在文件开头
QIODevice::Text 在读取时,将行结束符转换成
;在写入时,将行结束符转换成本地格式,例如 Win32 平台上是
QIODevice::Unbuffered 忽略缓存

二、文件 QFile

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

一般在构建QFile对象时便指定文件名,当然也可以使用setFileName)在其他任何时间进行设置。可以使用exists)来检査文件是否存在,remove)来删除一个文件。更多与文件系统相关的高级操作在QFilelnfo和QDir类中提供。

一个文件可以使用open)打开,使用close)关闭,使用flush)刷新。文件的数据读写一般使用QTextStream或者QDataStream来完成,不过也可以使用继承自QIODevice类的一些函数,比如read)、readLine)、readAll)和write),还有一次只操作一个字符的getChar)、putChar)和ungetChar)等函数。可以使用size)函数来获取文件的大小,使用seek)来定位到文件的任意位置,使用pos)来获取当前的位置,使用atEnd)来判断是否到达了文件的末尾。

(1)直接使用QFile读写文件

示例程序如下:

//直接使用QFile写文件
QFile fileW"test.txt");
if !fileW.openQIODevice::WriteOnly | QIODevice::Text))
	return;
fileW.write"first line!
second line");
fileW.close);

//直接使用QFile读文件
QFile fileR"test.txt");
if !fileR.openQIODevice::ReadOnly | QIODevice::Text))
	return;
while !fileR.atEnd))
{
	QByteArray line = fileR.readLine);
	qDebug) <<line;
}
fileR.close);

(2)使用文本流读/写文本文件

QTextStream类提供了一个方便的接口来读/写文本,可以在QIODevice、QByteArray和QString上进行操作。使用QTextStream的流操作符,可以方便地读/写单词、行和数字。示例程序如下:

//使用QTextStream文本流读文件
QFile fileW"test.txt");
if !fileW.openQIODevice::WriteOnly | QIODevice::Text))
	return -1;
QTextStream out&fileW);
out << "first line" << "
second line";
fileW.close);

//使用QTextStream文本流写文件
QFile fileR"test.txt");
if !fileR.openQIODevice::ReadOnly | QIODevice::Text))
	return -1;
QTextStream in&fileR);
while !in.atEnd))
{
	QString line = in.readLine);
	qDebug) <<line;
}

可以使用seek)来定位到一个指定位置,使用atEnd)判断是否还有可以读取的数据。如果调用了flush)函数,QText­Stream会清空写缓冲中的所有数据,并且调用设备的flush)函数。

在内部,QTextStream使用了一个基于Unicode的缓冲区,QTextStream使用QTextCodec来自动支持不同的字符集。默认的,使用QTextCodec ::codecForLocale)返回的编码来进行读写,也可以使用setCodec)函数来设置编码。

(3)使用数据流读/写二进制数据

QDataStream类实现了将QIODevice的二进制数据串行化。一个数据流就是一个二进制编码信息流,完全独立于主机的操作系统、CPU和字节顺序。数据流也可以读/写未编码的原始二进制数据。QDataStream类可以实现C+ +基本数据类型的串行化,比如char、Sh〇rt、im和char*等。而串行化更复杂的数据,是通过将数据分解为基本的数据类型来完成的。示例程序如下:

//使用QTextStream文本流读文件
QFile fileW"test.txt");
if !fileW.openQIODevice::WriteOnly))
    return -1;
QDataStream out&fileW);
//串行化字符串(写入时,要求强制转换为QString类型,否则写入的是乱码)
out << QString"the answer is");
//串行化整数
out << static_cast<qint32>42);
fileW.close);

//使用QTextStream文本流写文件
QFile fileR"test.txt");
if !fileR.openQIODevice::ReadOnly))
    return -1;
QDataStream in&fileR);
QString str;
qint32 num;
in >> str >> num;
qDebug) << str << num; //输出:"the answer is" 42
fileR.close);

写到数据流中的每一个条目都是使用一个预定义的格式写入的,这个格式依赖于条目的类型。(否则写入的会是乱码)支持的 Qt 类型包括 QBrush、QColor、QDateTime、QFom、QPixmap、 QString、QVariant和很多其他格式。

三、文件信息 QFilelnfo

QFilelnfo类提供了与系统无关的文件信息,包括文件的名称、在文件系统中的位置(路径)、文件的访问权限以及是否是一个目录或者符号链接等 。QFilelnfo也可以获取文件的大小和最近一次修改/读取的时间,还可以获取Qt资源的相关信息 。 QFilelnfo指向的文件可以在QFileinfo对象构建时设置,或者以后使用setFile)来设置。

QFileInfo可以使用相对(relative)路径或者绝对(absolute)路径来指向一个文件,还可以使用makeAbsolute)来将一个相对路径转换为绝对路径。
文件的类型可以使用isFile)、isDir)和isSymLink)来获取。 可以分别使用path)和fileName)来获取文件的路径和文件名,还可以使用baseName)来获取文件名中的基本名称,使用suffix)来获取文件名的后缀,使用completeSuffix)来获取复合后缀。
文件的日期可以使用created)、lastModified)和lastRead)来返回;
访问权限可以使用isReadable)、isWritable)和isExecutable)来获取;
文件的所有权可以使用owner)、ownerId)、group)和groupId)来获取。

新建Qt5控制台应用,名称为myFile,创建完成后将main.cpp文件的内容更改为:

#include <QtCore/QCoreApplication>
#include <QFileInfo>
#include <QTextCodec>
#include <QStringList>
#include <QDateTime>
#include <QDebug>

int mainint argc, char *argv[])
{
    QCoreApplication aargc, argv);

    // 以只写方式打开,如果文件不存在,那么会创建该文件
    QFile file"myfile.txt");
    if !file.openQIODevice::WriteOnly  | QIODevice::Text))
        qDebug) << file.errorString);
    file.write"helloQt!
yafeilinux");
    file.close);

    // 获取文件信息
    QFileInfo infofile);
    qDebug) << QObject::tr"绝对路径:") << info.absoluteFilePath) << endl
             << QObject::tr"文件名:") << info.fileName) << endl
             << QObject::tr"基本名称:") << info.baseName) << endl
             << QObject::tr"后缀:") << info.suffix) << endl
             << QObject::tr"创建时间:") << info.created) << endl
             << QObject::tr"大小:") << info.size);

    // 以只读方式打开
    if !file.openQIODevice::ReadOnly | QIODevice::Text))
        qDebug) << file.errorString);
    qDebug) << QObject::tr"文件内容:") << endl << file.readAll);
    qDebug) << QObject::tr"当前位置:") << file.pos);
    //移动文件开始读取位置为0
    file.seek0);
    QByteArray array;
    array = file.read5);
    qDebug) << QObject::tr"前5个字符:") << array
             << QObject::tr"当前位置:") << file.pos);
    //移动文件开始读取位置为15
    file.seek15);
    array = file.read5);
    qDebug) << QObject::tr"第16-20个字符:") << array;
    file.close);

    return a.exec);
}

执行程序,控制台输出如下:

"绝对路径:" "D:/Project/C++/Qt/myFile/build-myFile-Desktop_Qt_5_9_7_MinGW_32bit-Debug/myfile.txt"
"文件名:" "myfile.txt"
"基本名称:" "myfile"
"后缀:" "txt"
"创建时间:" QDateTime2019-06-17 16:58:01.230 中国标准时间 Qt::TimeSpecLocalTime))
"大小:" 20
"文件内容:"
"helloQt!
yafeilinux"
"当前位置:" 20
"前5个字符:" "hello" "当前位置:" 5
"第16-20个字符:" "linux"

四、临时文件 QTemporaryFile

QTemporaryFile类是一个用来操作临时文件的I/O设备,它可以安全地创建一个唯一的临时文件。当调用open)函数时便会创建一个临时文件,临时文件的文件名可以保证是唯一的,当销毁QTemporaryFile对象时,该文件会被自动删除掉。

在调用open)函数时,默认会使用QIODevice::ReadWrite模式,可以像下面的代码这样来使用QTemporaryFile类:

QTemporaryFile file;
if file.open)) 
{
    // 在这里对临时文件进行操作,file.fileName)可以返回唯一的文件名
}

在调用了close)函数后重新打开QTemporaryFile是安全的,只要QTemporaryFile的对象没有被销毁,那么唯一的临时文件就会一直存在而且由QTemporaryFile内部保持打开。临时文件默认会生成在系统的临时目录里,这个目录的路径可以使用QDir::tempPath)来获取。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平