Qt:QFile

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()

isReadable()

isSequential()

isTextModeEnabled()

isTransactionStarted() 

isWritable()

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。

读到以下三种情况时结束:

  1. 第一个\n;
  2. 读到maxSize - 1 bytes;
  3. 检测到Device data末尾。

例如,下面的代码显示了如何从一个文件中读取一行字符:

    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中可读的时候发送该信号。
上一篇:Winform中使用FileStream读取文件后,继续操作提示:it is being used by anothor process


下一篇:fs 常见开发流程