Learning Qt 5! (10):文件及其读写

学习文件操作!
Qt 学习之路 2(35):文件
Qt 学习之路 2(36):二进制文件读写
Qt 学习之路 2(37):文本文件读写

一图来看Qt 5中I/O设备的类:
qiodevice
看看Qfile的代码:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    /*这个in.txt文件要自己建,放在项目的build文件夹下,否则会Open file failed.*/
    QFile file("in.txt"); 
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Open file failed.";
        return -1;
    } else {
        while (!file.atEnd()) {
            qDebug() << file.readLine();
        }
    }

    /*有关文件本身的信息,比如文件名、文件所在目录的名字等,是通过QFileInfo获取,而不是
    自己分析文件路径字符串。*/
    QFileInfo info(file);
    qDebug() << info.isDir(); //检查该文件是否是目录
    qDebug() << info.isExecutable(); //检查该文件是否是可执行文件
    qDebug() << info.baseName(); //无路径并第一个.前的名称,此处为"in"
    qDebug() << info.completeBaseName(); //最后一个.前的名称,此处也为"in"
    qDebug() << info.suffix(); //获取文件后缀名,此处为"txt"
    qDebug() << info.completeSuffix(); //第一个.后的后缀,此处也为"txt"

    return app.exec();
}

二进制流的操作用QDataStream,看代码:

	QFile file("file.dat"); //也要先在项目的build文件夹下创建一个file.dat
	file.open(QIODevice::WriteOnly);
	//将刚刚创建的file对象的指针传递给一个QDataStream实例out
	QDataStream out(&file);
	//将“the answer is”和数字 42 输出到数据流
	out << QString("the answer is");
	out << (qint32)42; 
	/*最好使用 Qt 整型来进行读写,比如程序中的qint32。这保证了在任意平台和任意编译器都能够
	有相同的行为。*/
	//为性能起见,数据只有在文件关闭时才会真正写入。因此,我们必须在最后添加一行代码:
	file.close(); // 如果不想关闭文件,可以使用 file.flush();

运行代码后用记事本打开file.dat文件,会看到数字“42”的部分变成了星号*,与ASCII码对应。
再来试试用QDataStream读取file.dat:

	file.open(QIODevice::ReadOnly);
	QDataStream in(&file);
	QString str;
	qint32 a;
	in >> str >> a;
	qDebug() << str << a;

唯一需要注意的是,你必须按照写入的顺序,将数据读取出来。也就是说,程序数据写入的顺序必须预先定义好。在这个例子中,我们首先写入字符串,然后写入数字,那么就首先读出来的就是字符串,然后才是数字。顺序颠倒的话,程序行为是不确定的,严重时会直接造成程序崩溃。

由于二进制流是纯粹的字节数据,带来的问题是,如果程序不同版本之间按照不同的方式读取(前面说过,Qt 保证读写内容的一致,但是并不能保证不同 Qt 版本之间的一致),数据就会出现错误。因此,我们必须提供一种机制来确保不同版本之间的一致性。通常,我们会使用如下的代码写入:

	QFile file("file.dat");
	file.open(QIODevice::WriteOnly);
	QDataStream out(&file);
	
	// 写入魔术数字和版本
	/*所谓魔术数字,是二进制输出中经常使用的一种技术。二进制格式是人不可读的,并且通常具有相同
	的后缀名(比如 dat 之类),因此我们没有办法区分两个二进制文件哪个是合法的。所以,我们定
	义的二进制格式通常具有一个魔术数字,用于标识文件的合法性。在本例中,我们在文件最开始写入
	0xA0B0C0D0,在读取的时候首先检查这个数字是不是0xA0B0C0D0。如果不是的话,说明这个文件不
	是可识别格式,因此根本不需要去继续读取。魔术数字是一个 32 位的无符号整型,因此我们使用
	quint32来得到一个平台无关的 32 位无符号整型。*/
	out << (quint32)0xA0B0C0D0;
	/*文件的不同版本之间也可能存在差异:我们可能在第一版保存整型,第二版可能保存字符串。为了
	标识不同的版本,我们只能将版本写入文件。比如,现在我们的版本是 123。*/
	out << (qint32)123;
	/*Qt不同版本之间的读取方式可能也不一样。这样,我们就得指定Qt按照哪个版本去读。这里,我们
	指定以Qt 4.0格式去读取内容。*/
	out.setVersion(QDataStream::Qt_4_0);

// 写入数据
out << lots_of_interesting_data;

file.close();

加入了魔术数字和版本后,读取文件时也要做相应的判断:

	QFile file("file.dat");
	file.open(QIODevice::ReadOnly);
	QDataStream in(&file);
	
	// 检查魔术数字
	quint32 magic;
	in >> magic;
	if (magic != 0xA0B0C0D0) {
	    return BAD_FILE_FORMAT;
	}
	
	// 检查版本
	qint32 version;
	in >> version;
	if (version < 100) {
	    return BAD_FILE_TOO_OLD;
	}
	if (version > 123) {
	    return BAD_FILE_TOO_NEW;
	}
	
	if (version <= 110) {
	    in.setVersion(QDataStream::Qt_3_2);
	} else {
	    in.setVersion(QDataStream::Qt_4_0);
	}
	// 读取数据
	in >> lots_of_interesting_data;
	if (version >= 120) {
	    in >> data_new_in_version_1_2;
	}
	in >> other_interesting_data;

QDataStream同QIODevice的区别在于,QDataStream提供流的形式,性能上一般比直接调用原始 API 更好一些。通过下面一段代码看看什么是流的形式:

    QFile file("file.dat");
    file.open(QIODevice::ReadWrite);

    QDataStream stream(&file);
    QString str = "the answer is 42";
    QString strout;

    stream << str;
    file.flush();
    /*所谓流,就像水流一样,它的游标会随着输出向后移动。当使用<<操作符输出之后,流的游标
    已经到了最后,此时你再去读,当然什么也读不到了。所以你需要在输出之后重新把游标设置为
    0的位置才能够继续读取。*/
    stream.device()->seek(0); //游标设置为0
    stream >> strout;
    qDebug() << strout;

文本文件的读取用QTextStream,看看代码:

	QFile data("file.txt");
	/*QIODevice::Truncate是以重写的方式打开,在写入新的数据时会将原有数据全部清除,游标
	设置在文件开头。*/
	if (data.open(QFile::WriteOnly | QIODevice::Truncate)) { 
    	QTextStream out(&data);
    	out << "The answer is " << 42;
	}
    data.close();

    if (data.open(QFile::ReadOnly)) {
        QTextStream in(&data);
        QString str;
        int ans = 0;
        in >> str >> ans;
        qDebug() << str;
    }

注意我们这里使用的是 >> 重定向,这个函数会以空白字符作为分隔符。因此读取时str只能读出“The”,如果再用一个QString,再读出一个“answer“。

为方便起见,QTextStream同std::cout一样提供了很多描述符,被称为 stream manipulators。因为文本文件是供人去读的,自然需要良好的格式(相比而言,二进制文件就没有这些问题,只要数据准确就可以了)。这些描述符是一些函数的简写,我们可以从文档中找到。

About This Book, Unleash the power of Qt 5 with C++14Integrate useful third-party libraries such as OpenCVPackage and deploy your application on multiple platforms, Who This Book Is For, This book will appeal to developers and programmers who would like to build GUI-based applications. Knowledge of C++ is necessary and the basics of Qt would be helpful., What You Will Learn, Create stunning UIs with Qt Widget and Qt QuickDevelop powerful, cross-platform applications with the Qt frameworkDesign GUIs with the Qt Designer and build a library in it for UI previewHandle user interaction with the Qt signal/slot mechanism in C++Prepare a cross-platform project to host a third-party libraryBuild a Qt application using the OpenCV APIUse the Qt Animation framework to display stunning effectsDeploy mobile apps with Qt and embedded platforms, In Detail, Qt 5.7 is an application development framework that provides a great user experience and develops full-capability applications with Qt Widgets, QML, and even Qt 3D., This book will address challenges in successfully developing cross-platform applications with the Qt framework. Cross-platform development needs a well-organized project. Using this book, you will have a better understanding of the Qt framework and the tools to resolve serious issues such as linking, debugging, and multithreading. Your journey will start with the new Qt 5 features. Then you will explore different platforms and learn to tame them. Every chapter along the way is a logical step that you must take to master Qt. The journey will end in an application that has been tested and is ready to be shipped., Style and approach, This is an easy-to-follow yet comprehensive guide to building applications in Qt. Each chapter covers increasingly advanced topics, with subjects grouped according to their complexity as well as their usefulness. Packed with practical examples and explanations, Mastering Qt contains everything you need to take your applications to the next level.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值