QFile
0、说明
QFile是读写文件的类,这里的文件包括文本文件、二进制文件、资源文件。
通常情况下,文件读写使用QFile、QTextStream、QDataStream就够了。
file name在构造QFile时传入,或者通过setFileName()自己设置。不管什么OS,QFile中的分隔符都是 '/'。其它分隔符均不支持。
通过exists()检查文件是否存在,用remove()移除文件(更多文件系统相关的操作可见QFileInfo and QDir.)
通过open()打开文件,close()关闭文件,flush()刷新文件。
文件中的数据通常用QDataStream or QTextStream读写,当然也可以直接调用从QIODevice继承下来的read()、readLine()、readAll()、write()进行读写。QFile也继承了getChar()、putChar()、ungetChar(),这些方法一次操作单个字符。
文件大小通过size()得到。当前访问到的数据所在文件中的位置通过pos()完成定位,移动到一个新的位置可以用seek()方法。如果移动到了文件末尾,atEnd()方法将返回true。
①直接读取文件
QFile file("in.txt"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; while(!file.atEnd()){ QByteArray line = file.readLine(); process_line(line); }
QIODevice::Text告诉Qt编译器,把Windows风格的行间隔符 \r\n 转换为 C++风格的 \n。默认情况下,QFile被认为是二进制文件,在读取过程中并不进行转换。
②使用Stream读取文件
QFile file("in.txt"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream in(&file); while(!in.atEnd()){ QString line = in.readLine(); process_line(line); }
QTextStream会把磁盘中的8bit 数据转换为16bit 的Unicode QString。默认情况下,编译器认为认为用户系统的编码方式为UTF-8,如果要修改编码方式,可以调用QTextStream::setCodec()。
③用Stream写入文件
如果要写入文本,我们可以用重载运算符 <<,运算符左侧是QTextStream对象,右侧可以是任意数据类型。
QFile file("out.txt"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream out(&file); out << "The magic number is: "<<49<<"\n";
如果用QDataStream读写,用法是相似的——我们可以用<<来write,用>>来read。具体用法可以查看QDataStream官方文档:QDataStream。
当我们使用QFile、QFileInfo、QDir来访问文件系统时,我们用的是Unicode文件名。在Unix中,这些文件名将被转换为UTF-8编码,如果我们想调用标准C++ API(如<cstdio>、<iostream>)去访问file而非QFile,我们可以用encodeName()和decodeName()在Unicode和UTF-8的file name间互相转换。
在Unix系统中,有些特殊的系统文件,它们的size()总返回0,但是我们仍能从中读取许多数据,这些数据在调用read()方法时获取。此时我们不能用atEnd()来判断是否读到了末尾,而只能用readAll()一次读完,或者重复用read()、readLine()直到没有数据可读。下一个例子中,我们用QTextStream按行读取/proc/modules文件:
QFile file("/proc/modules"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream in(&file); QString line = in.readLine(); while( !line.isNull() ){ process_line(line); line = in.readLine(); }
最后,需要注意的是QFile是继承自QIODevice的,而所有read、write的相关方法都是在QIODevice中定义的,所以具体的读写方法见QIODevice。
1、模块和加载项
Header |
#include<QFile> |
qmake | QT += core |
Inherits | QFileDevice |
Inherited By | QTemporaryFile |
2、构造
QFile(QString name, QObject *parent) |
QFile(QObject *parent) |
QFile(QString name) |
QFile() |
3、实例方法
返回值类型 |
方法 |
说明 |
bool | copy(const QString &newName) | |
bool | exists() | |
bool | link(const QString &linkName) | |
bool | moveToTrash() | |
bool | open(FILE *fh, QIODevice::OpenMode mode, QFileDevice::FileHandleFlags handleFlags = DontCloseHandle) | |
bool | open(int fd, QIODevice::OpenMode mode, QFileDevice::FileHandleFlags handleFlags = DontCloseHandle) | |
bool | remove() | |
bool | rename(const QString &newName) | |
void | setFileName(const QString &name) | |
QString | symLinkTarget() |
4、静态方法
方法返回值 |
方法 |
说明 |
bool | copy(const QString &fileName, const QString &newName) | |
QString | decodeName(const QByteArray &localFileName) | |
QString | decodeName(const char *localFileName) | |
QByteArray | encodeName(const QString &fileName) | |
bool | exists(const QString &fileName) | |
bool | link(const QString &fileName, const QString &linkName) | |
bool | moveToTrash(const QString &fileName, QString *pathInTrash = nullptr) | |
bool | permissions(const QString &fileName) | |
bool | remove(const QString &fileName) | |
bool | rename(const QString &oldName, const QString &newName) | |
bool | resize(const QString &fileName, qint64 sz) | |
bool | setPermissions(const QString &fileName, QFileDevice::Permissions permissions) | |
QString | symLinkTarget(const QString &fileName) |
QIODevice
0、说明
QIODevice中实现了Qt中的所有I/O方法,其他用到IO的类如QFile、QBuffer、QTcpSocket,都是从这个类继承而来。
QIODevice是抽象类,不能实例化,但是可以用多态技术,来定义一个QIODevice去承接一个从它继承而来的实现类。
在读写之前,open()一个文件时必须先设置正确的OpenMode(如ReadOnly或ReadWrite)。之后就可以调用write()、putChar()向其中write,调用read()、readLine()、readAll()来read。完成read、write后调用close()。
有两种Device:①随机访问;②顺序访问。
①随机访问:调用seek()转移到文件中任意位置,调用pos()查看当前位置。QFile、QBuffer是随机访问的典型;
②顺序访问:不能从任意位置开始。数据读取必须一个接一个。QTcpSocket、QProcess是顺序访问的典型。
如何判断是哪种device呢?调用isSequential()方法。
QIODevice会发射readyRead()当新的数据已经准备好reading,例如,读取的时候,有新的数据到达网络或额外的数据被添加到文件中。我们可以调用bytesAvailable()来判断现在有多少个bytes是准备读取的。当QTcpSocket程序处理异步数据时,经常会有数据不定时的到达,这时bytesAvailable()通常和readyRead()信号联用。当有数据要write时,QIODevice会发射bytesWritten()信号,此时用bytesToWrite()可以知道有多少bytes等待写入。
1、模块和加载项
Header |
#include<QIODevice> |
qmake | QT += core |
Inherits | QObject |
Inherited By | QFileDevice |
2、构造
QIODevice(QObject * parent) | 给Parent构造一个QIODevice |
QIODevice() | 构造一个QIODevice |
3、静态属性
类型 |
属性 |
说明 |
flags | OpenMode | |
enum | OpenModeFlag |
这个enum是用于open()的参数,主要是描述文件打开时采用的device。如果要查看这个device,可以通过openMode()返回。
常用的Mode有ReadOnly、WriteOnly、ReadWrite、Append,对应的device顾名思义。
4、对象方法
返回值类型 |
方法 |
说明 |
virtual bool | atEnd() |
如果当前的read、write位置已经到了device末尾返回true,否则返回false。 在某些系统文件中,atEnd()总是返回false,这种文献的读写可见QFile的说明部分。 |
virtual qint64 | bytesAvailable() | 返回有多少bytes可被读取。常用于顺序读写。 |
virtual qint64 | bytesToWrite() | 用于buffer Device,该方法返回有多少bytes正等待write。对于没有buffer的Device,该方法返回0。 |
virtual bool | canReadLine() |
每当有完整的一行数据可以从device中读取时返回true,否则false。 对于非buffer Device,该方法返回false。 该方法常和信号readyRead()结合使用。 |
virtual void | close() | 先发送aboutToClose()信号,然后关闭Device并设置它的OpenMode为NotOpen。此外error string也会被重置。 |
void | commitTransaction() |
完成事务读取。 对于顺序Device,保存数据的内部buffer在事务期将被丢弃。 |
int | currentReadChannel() | 返回当前read channel的索引号 |
int | currentWriteChannel() | 返回当前write channel的索引号 |
QString | errorString() | 返回最后一次device error的描述 |
bool | getChar(char *c) | 读取单个char存到c中,成功时返回true,否则false |
bool |
isOpen() |
Device为非NotOpen时返回true,否则false; 如果有data可以从device中读取时返回true,否则false。常用于检查Device的Mode是否包含ReadOnly 当Device是顺序Device时返回true,否则false 当Text标记开启时返回true,否则false 如果某个事务正在处理,返回true,否则false 当有数据可以向Device中写入时返回true,常用于检查Mode是否包含WriteOnly。 |
virtual bool | open(QIODevice::OpenMode mode) |
打开Device并将它的OpenMode设置为mode。 QFile的open方法重载了它,并且可以同时指定打开文件和Mode |
QIODevice::OpenMode | openMode() | 返回当前Device的Mode,如ReadOnly或WriteOnly |
qint64 | peek(char *data, qint64 maxSize) |
从Device中读取最多maxSize bytes的数据到data中,并不会改变pos,即pos一直指向读取开始的位置。返回读取的bytes数。 发生错误时返回-1,没有可读数据时返回0。 |
QByteArray | peek(qint64 maxSize) | 从Device中读取至多maxSize bytes,返回读取到的数据,类型是QByteArray。 |
virtual qint64 | pos() |
随机访问时,返回当前读写到的文件位置。 对于顺序Device或者关闭的Device,返回0。 当前的 read/write位置会在QIODevice内部维护,所以重载该方法并不是必要的。 |
bool | putChar(char c) | 向Device中写入单个char,成功时返回true。 |
qint64 | read(char *data, qint64 maxSize) |
从Device中读取至多maxSize bytes到data中,返回读取到的bytes数量。错误发生时返回-1。 当没有数据可读时返回0。 |
QByteArray | read(qint64 maxSize) |
重载方法。 从Device中读取至多maxSize bytes,返回读取到的data对应的QByteArray。 发生错误时不报错,只是返回空QByteArray。 |
QByteArray | readAll() | 读取Device中所有剩余的数据,返回读到的data对应的QByteArray。 |
int | readChannelCount() | 当Device打开时,返回可用的read channel的数量。 |
qint64 | readLine(char *data, qint64 maxSize) |
从Device中读取一行ASCII字符,至多maxSize-1 bytes,保存读取到的数据到data中,返回读取到的bytes数。 无法读取时,返回0。发生错误时,返回可读的长度,如果长度为0返回-1。 每次读取都会在data后边加一个\0,所以maxSize必须大于1。 读到以下三种情况时结束:
例如,下面的代码显示了如何从一个文件中读取一行字符: QFile file("box.txt"); if(file.open(QFile::ReadOnly)){ char buf[1024]; qint64 lineLength = file.readLine(buf , sizeof(buf)); if(lineLength != -1){ //当buf中已经读取到了一行数据 } } 行结束符'\n'也会包含在buffer中。如果没有读完一行便到了maxSize - 1,那么该行便不会完整读入buffer。 |
QByteArray | readLine(qint64 maxSize = 0) | 读一行,但不超过maxSize个char,将读取结果以QByteArray形式返回 |
virtual bool | reset() |
重置pos到随机访问Device开头。 需要注意的是,当我们用QTextStream读取QFile,不能用reset()回到文件头,而应该用QTextStream::seek() |
void | rollbackTransaction() |
事务回滚。 恢复input stream到startTransaction()调用前。 该方法常用于在提交事务前检测到未完成read的时候。 |
virtual bool | seek(qint64 pos) | 用于随机方法Device,该方法重置当前位置到pos。 |
void | setCurrentReadChannel(int channel) | 设置当前QIODevice的read channel为给定的channel,当前的channel常被方法read()、readAll()、readLine()、getChar()调用。当前channel会激发QIODevice发送readyRead()信号。 |
void | setCurrentWriteChannel(int channel) | 设置当前QIODevice的write channel为给定的channel,当前的channel用于方法write()、putChar()。它会激发QIODevice发送bytesWritten()信号。 |
void | setTextModeEnabled(bool enabled) |
如果参数是true,该方法会给Device设置Text标志,否则Text标志会被移除。 该特性对于那些提供了行结尾处理方法的类很有帮助。 |
virtual qint64 | size() |
对于随机访问Device,该方法返回Device的大小。 对于顺序访问Device,该方法返回byteAvailable() |
qint64 | skip(qint64 maxSize) |
从文件开头跳转到maxSize bytes处。返回实际跳转的byte数,出错返回-1。 该方法可以应用到全部Device中,包括随机访问和顺序访问。 该方法常和peek()联合使用,跳过不需要的数据。 对于随机访问,它可以跳转到当前pos之前,负的maxSize是非法的。 |
void | startTransaction() |
在Device上开始一个新的read事务。 该方法会定义一个恢复点。在顺序Device中,数据会在内部备份以防止由于恢复导致的不完整的读取。 在随机Device,该方法存储当前pos。调用commitTransaction()、rollbackTransaction()来完成事务。 |
void | ungetChar(char c) |
把单个字符c放回Device中,并后移当前pos。 该方法常用于作为getChar()方法的"undo"方法。 |
virtual bool | waitForBytesWritten(int msecs) | |
virtual bool | waitForReadyRead(int msecs) | |
qint64 | write(char * data, qint64 maxSize) |
从data中写至多maxSize bytes到Device中,返回实际写入的bytes数。 发生错误时返回-1 |
qint64 | write(char * data) | 把data写入Device中,返回实际写入的bytes数。 |
qint64 | write(QByteArray byteArray) | 把byteArray的内容写到Device中,返回实际写入的bytes数。 |
int | writeChannelCount() | 当Device为open时返回可用的write channel数量,否则返回0 |
5、信号
信号 |
说明 |
aboutToClose() | 当Device要关闭时发送该信号。 |
bytesWritten(qint64 bytes) | 当有数据已经写入Device的对应的write channel时发送该信号。 |
channelBytesWritten(int channel, qint64 bytes) | 当有数据已经写入Device中时发送该信号。 |
channelReadyRead(int channel) | 当有新数据要从Device中可读的时候发送该信号。 |
readChannelFinished() | 输入流关闭时发送该信号。 |
readyRead() | 当有新数据要从Device对应的read channel中可读的时候发送该信号。 |