QProcess、QTcpSocket、QUdpSoctet 和 QSslSocket 是顺序访问设备,只能从头到尾读下去不能回头。 QFile、QTemporaryFile 和 QBuffer 是随机访问设备,可以访问任意位置任意次数,还可以使用 QIODevice::seek() 函数来重新定位文件访问位置指针。
#include <Qapplication>#include <QDebug>#include <QFile>#include <QFileInfo>int main(int argc, char *argv[]){ QApplication app(argc, argv); QFile file("C:/Users/Aaron/Documents/LenovoHdReport.txt"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Open file failed."; return -1; } else { while (!file.atEnd()) { qDebug() << file.readLine(); //一次读一行 } } QFileInfo info(file); qDebug() << info.path(); //返回路径 qDebug() << info.isDir(); //是否是路径 qDebug() << info.isExecutable(); //是否可执行 qDebug() << info.baseName(); //Returns the base name of the file without the path. qDebug() << info.completeBaseName();//Returns the complete base name of the file without the path. qDebug() << info.suffix(); //Returns the suffix of the file. qDebug() << info.completeSuffix();//Returns the complete suffix of the file. return app.exec();}complateSuffix , suffix 区别可以直接看文档的例子。
QDataStream 提供了基于 QIODevice 的二进制数据的序列化。 数据流是一种二进制流,完全不依赖于底层操作系统、CPU 或者字节顺序(大端或小端)。例如,在安装了 Windows 平台的 PC 上面写入的一个数据流,可以不经过任何处理,直接拿到运行了 Solaris 的 SPARC 机器上读取。由于数据流就是二进制流,因此我们也可以直接读写没有编码的二进制数据,例如图像、视频、音频等。
QDataStream 既能够存取 C++ 基本类型,如 int、char、short 等,也可以存取复杂的数据类型,例如自定义的类。实际上,QDataStream 对于类的存储,是将复杂的类分割为很多基本单元实现的。
QFile file("file.dat"); if(file.open(QIODevice::WriteOnly|QIODevice::ReadOnly)){ QDataStream out(&file); //写入 out << QString("the answer is"); out << (qint32)42; file.close(); }else{ return -1; } if(file.open(QIODevice::ReadOnly)){ QDataStream in(&file); //读取 QString str; qint32 a = 3; in>>str>>a; qDebug()<<str<<a; file.close(); }二进制流在写入的时候会在没个数据前面加上这个数据的长度。 注意:读取顺序必须和写入顺序一致。毕竟是二进制数据流,错一位就改不回来了。 而且可以看到先把文件关闭了又打开才读取的数据,因为流数据在写入的时候游标是跟着向后移动的,游标在文件末尾,如果直接读取显然是拿不到数据的。当然也可以用方法:out.device()->seek(0)
将游标重新移动到开头位置。
由于二进制流是纯粹的字节数据,带来的问题是,如果程序不同版本之间按照不同的方式读取(前面说过,Qt 保证读写内容的一致,但是并不能保证不同 Qt 版本之间的一致),数据就会出现错误。因此,我们必须提供一种机制来确保不同版本之间的一致性。
QFile file("file.dat");file.open(QIODevice::WriteOnly);QDataStream out(&file);// 写入魔术数字和版本out << (quint32)0xA0B0C0D0;out << (qint32)123;out.setVersion(QDataStream::Qt_4_0);// 写入数据out << lots_of_interesting_data;这样一来,在读取文件的时候,先判断魔术数字以及版本的一致性,即可保证。
QTextStream 的写入和QDataStream并无二致。但读取则不样。因为存取的是文本数据,并不像二进制流一样会存上每个数据的长度。 将上面的例子改成文本流,就会发现 输出时 str == the answer is 42. 而 a 并没有重新赋值。 文本流 可以设置编码格式 stream.setCodec("UTF-8");
另外:另外,为方便起见,QTextStream 同 std::cout 一样提供了很多描述符,被称为 stream manipulators。因为文本文件是供人去读的,自然需要良好的格式(相比而言,二进制文件就没有这些问题,只要数据准确就可以了)。这些描述符是一些函数的简写,我们可以从文档中找到:
Qt 容器
QList:这是至今为止提供的最通用的容器类。它将给定的类型 T 的对象以列表的形式进行存储,与一个整型的索引关联。QList 在内部使用数组实现,同时提供基于索引的快速访问。我们可以使用 QList::append() 和 QList::prepend() 在列表尾部或头部添加元素,也可以使用 QList::insert() 在中间插入。相比其它容器类,QList 专门为这种修改操作作了优化。QStringList 继承自 QList。
QLinkedList:类似于 QList,除了它是使用遍历器进行遍历,而不是基于整数索引的随机访问。对于在中部插入大量数据,它的性能要优于 QList。同时具有更好的遍历器语义(只要数据元素存在,QLinkedList 的遍历器就会指向一个合法元素,相比而言,当插入或删除数据时,QList 的遍历器就会指向一个非法值)。
QVector< T>:用于在内存的连续区存储一系列给定类型的值。在头部或中间插入数据可能会非常慢,因为这会引起大量数据在内存中的移动。
QStack< T>:这是 QVector 的子类,提供了后进先出(LIFO)语义。相比 QVector,它提供了额外的函数:push(),pop() 和 top()。
QQueue< T>:这是 QList 的子类,提供了先进先出(FIFO)语义。相比 QList,它提供了额外的函数:enqueue(),dequeue() 和 head()。
QSet< T>:提供单值的数学上面的集合,具有快速的查找性能。
QMap< Key, T>:提供了字典数据结构(关联数组),将类型 T 的值同类型 Key 的键关联起来。通常,每个键与一个值关联。QMap 以键的顺序存储数据;如果顺序无关,QHash 提供了更好的性能。
QMultiMap< Key, T>:这是 QMap 的子类,提供了多值映射:一个键可以与多个值关联。
QHash< Key, T>:该类同 QMap 的接口几乎相同,但是提供了更快的查找。QHash 以字母顺序存储数据。
QMultiHash< Key, T>:这是 QHash 的子类,提供了多值散列。
遍历器: QListIterator< T> 只读遍历器; QMutableListIterator< T> 读写遍历器。其他的容器都一样。
两种容器的遍历方式
QMutableListIterator<int> i(list);while (i.hasNext()) { if (i.next() > 128) { i.setValue(128); //也可以直接 i = 128; }}QList<QString> list;list << "A" << "B" << "C" << "D";QList<QString>::iterator i;for (i = list.begin(); i != list.end(); ++i) { *i = (*i).toLower();}另外 foreach() 也是可以的。
新闻热点
疑难解答