Qt知识回顾(十四)——文件、目录和输出/输出

文件和目录

输入/输出设备

  QIODevice类是Qt中所有I/O设备的基础接口类,为诸如QFile、QBuffer和QTcpSocket等支持读/写数据块的设备提供了一个抽象接口。QIODevice类是抽象的,无法被实例化,一般是使用它所定义的接口来提供设备无关的I/O功能。
  访问一个设备以前,需要使用open()函数打开该设备,而且必须指定正确的打开模式。QIODevice中所有的打开模式由QIODevice::OpenMode枚举类型定义,其取值如下表,其中的一些值可以使用按位或符号"|"来同时使用。打开设备后可以使用write()或者putChar()来进行写入,使用read()、readLine()或者readAll()进行读取,最后使用close()关闭设备。

常量描述
QIODevice::NotOpen设备没有打开
QIODevice::ReadOnly设备以只读方式打开,这时无法写入
QIODevice::WriteOnly设备以只写方式打开,这时无法读取
QIODevice::ReadWrite设备以读/写方式打开
QIODevice::Append设备以附加模式打开,所有的数据都将写入到文件的末尾
QIODevice::Truncate如果可能,设备在打开前会被截断,设备先前的所有内容都将丢失
QIODevice::Text当读取时,行结尾终止符会被转换为”\n“;当写入时,行结尾终止符会被转换为本地编码
QIODevice::Unbuffered绕过设备所有的缓冲区

  QIODevice会区别两种类型的设备:随机存储设备和顺序存储设备:
  >随机存取设备支持使用seek()函数来定位到任意的位置。文件中的当前位置可以使用pos()函数来获取。这样的设备有QFile、QBuffer等。
  >顺序存储设备不支持定位到任意的位置,数据必须一次性读取。pos()和size()等函数无法在操作顺序设备时使用。这样的设备有QTcpSocket、QProcess等。
  可以在程序中使用isSequential()函数来判断设备的类型。通过子类化QIODevice可以为自己的I/O设备提供相同接口,要子类化QIODevice,则只需要重新实现readData()和writeData()两个函数。QIODevice的一些子类,比如QFile和QTcpSocket,都使用了内存缓冲区进行数据的中间存储,这样减少了设备的访问次数,使得getChar()和putChar()等函数可以快速执行,而且可以在内存缓冲区上进行操作,而不用直接在设备上进行操作。但是,一些一些特定的I/O操作使用缓冲区却无法很好地工作,这时就可以在调用open()函数打开设备时使用QIODevice::Unbuffered模式来绕过所有的缓冲区。

文件操作

1.文件QFile
  QFile类提供了一个用于读/写文件的接口,它是一个可以用来读/写文本文件、二进制文件和Qt资源的I/O设备。QFile可以段都可以单独使用,也可以和QTextStream或者QDataStream一起使用,这样会更方便。
  一般在构建QFile对象时便指定文件名,当然也可以使用setFileName()进行设置。无论在哪种操作系统上,文件名路径中的文件分隔符都需要使用“/”符号。可以使用exist()来检查文件是否存在,使用remove()来删除一个文件。
  一个文件可以使用open()打开,使用close()关闭,使用flush()刷新。文件的数据读/写一般使用QDataStream或者QTextStream来完成,不过也可以使用继承自QIODevice类的一些函数,比如read()、readLine()、readAll()和write(),还有一次只操作一个字符的getChar()、putChar()和ungetChar()等函数.可以使用size()来获取文件的大小,使用seek()来定位到文件的任意位置,使用pos()来获取当前的位置,使用atEnd()来判断是否到达了文件的末尾。

2.文件QFileInfo
  QFileInfo类提供了与系统无关的文件信息,包括文件的名称、在文件系统中的位置(路径)、文件的访问权限以及是否是一个目录或者符号链接等。QFileInfo也可以获取文件的大小和最近一次修改/读取的时间。还可以获取Qt资源的相关信息。
  QFileInfo类可以使用相对路径或者绝对路径来指向一个文件,使用isRelative()函数可以判断一个QFileInfo对象使用的是相对路径还是绝对路径,还可以使用maskAbsolute()来将一个相对路径转换为绝对路径。QFileInfo指向的文件可以在QFileInfo对象构建时设置,或者使用setFile()来设置。可以使用exist()来查看文件是否存在,使用size()获取文件的大小。文件的类型可以使用isFile()、isDir()和isSymLink()来获取,symLinkTarget()函数可以返回符号链接指向的文件的名称。
  可以分别使用path()和fileName()来获取文件的路径和文件名,还可以使用baseName()来获取文件名的基本名称,使用suffix()来获取文件的后缀,使用completeSuffix()来获取复合后缀。文件的日期可以使用created()、lastModified()和lastRead()来返回;访问权限可以使用owner()、ownerId()、group()和groupId()来获取;还可以使用permission()函数将文件的访问权限和所有权一次性读取出来。
3.临时文件QTemporaryFile
  QTemporaryFile类是一个用来操作临时文件的I/O设备,它可以安全地创建一格唯一的临时文件。当调用open()函数时便会创建一个临时文件,临时文件的文件名可以保证是唯一的;当销毁QTemporaryFile对象时,该文件会自动删除掉。在调用open()函数时,默认会使用QIODevice::ReadWrite模式,调用了close()函数后重新打开QTemporaryFile是安全地,只要QTemporaryFile的对象没有被销毁,那么唯一的临时文件就会一直存在而且由QTemporaryFile内部保持打开。临时文件默认会生成在系统的临时目录里,这个目录的路径可以使用QDir::tempPath()来获取。

目录操作

1.目录QDir
  QDir类用来访问目录结构及其内容,可以操作路径名、访问路径和文件相关信息、操作底层的文件系统,还可以访问Qt的资源环境。Qt使用“/”作为通用的目录分隔符和URLs的目录分割符,如果使用“/”作为目录分隔符,则Qt会自动转换路径来适应底层的操作系统。QDir可以使用相对路径或者绝对路径来指向一格文件。
  可以使用isRelative()和isAbsolute()来判断一格QDir是否使用了相对路径和绝对路径,还可以使用maskAbsolute()来将一格相对路径转换为绝对路径。一个目录的路径可以使用path()函数获取,使用setPath()函数可以设置新的路径,使用absolutePath()函数可以获取绝对路径。目录名可以使用dirName()函数获取,这通常返回绝对路径中的最后一个元素;然而如果QDir代表当前目录,那么会返回“.”。目录的路径也可以使用cd()和cdUp()函数来改变,当使用一个存在的目录的名字来调用cd()时,QDir对象就会转换到指定的目录;而cdUp()会跳转到父目录,cdUp()和cd(…)是等效的。可以使用mkdir()来创建目录,使用rename()进行重命名,使用rmdir()删除目录。可以使用exists()函数来测试指定的目录是否存在,使用isReadable()和isRoot()等函数来测试目录的属性。使用refresh()函数可以重新读取目录的数据。
  目录中会包含很多条目,入文件、目录和符号链接等。一个目录中的天幕数目可以使用count()来返回,所有条目的名称列表可以使用emtryList()来获取;如果需要一个条目的信息,则可以使用entryInfoList()函数来获取一个QFileInfo对象的列表,可以使用filePath()和absoluteFilePath()来获取一个目录中的文件和目录的路径,filePath()会返回指定文件或目录与当前QDir对象所在路径的相对路径,而absoluteFilePath()会返回绝对路径。文件可以使用remove()函数来移除,但是目录只能使用rmdir()函数来移除。可以应用一个名称过滤器来使用通配符指定一个模式进行文件名的匹配,一个属性过滤器可以选取条目的属性并且可以区分文件和目录,还可以设置排序顺序。名称过滤器就是一个字符串列表,可以使用setNameFilters()函数来设置。
  属性过滤器是按位或组合在一起的过滤器组成,可以使用setFilter()来设置,排序顺序使用setSorting()来设置,他需要指定按位或组合在一起的排序标志QDir::SortFlags,所有的排序标志可以在QDir的帮助文档中进行查看,包含了按名称、时间、大小等排序方式。可以使用match()函数来测试一个文件名是否匹配一个过滤器。设置好过滤器和排序标志后,就可以调用entryList()或者entryInfoList()来获取指定条件的条目了。
  要访问一些常见的目录,则可以使用一些静态函数来完成,它们可以返回QDir对象或者QString类型的绝对路径,这些函数如下表所示:

返回类型为QDir返回类型为QString返回值
current()currentPath()应用程序的工作目录
home()homePath()用户的home目录
root()rootPath()root根目录
temp()tempPath()系统存放临时文件的目录

  使用setCurrent()静态函数也可以设置应用程序的工作目录。如果要查找包含应用程序可执行文件的目录,则可以使用QCoreApplication::applicationDirPath()函数。使用drives()函数可以返回系统的根目录,在Windows上会返回QFileInfo对象的列表,其中包含了“C:/”和“D:/”等;在其他操作系统上们会返回只包含根目录的一个列表。路径中包含“.”元素表示路径中的当前目录,“. .”元素表示父目录,可以使用canonicalPath()函数来返回一个规范的路径,该路径中不包含符号链接和冗余的“.”和". ."元素。cleanPath()函数可以一处路径中冗余的“/”和“.”或者“. .”。静态函数toNativeSeparators()可以将路径中的“/”分隔符转换为适合底层操作系统的分隔符。

2.文件系统监视器QFileSystemWatcher
  QFileSystemWatcher类提供了一个接口来监控文件和目录的修改,通过监视一个指定路径的列表来监控文件系统中文件和目录的改变。调用addPath()来监视一个指定的文件或者目录,多个路径可以使用addPaths()函数来添加,现有的路径可以使用removePath()和removePaths()函数来移除。QFileSystemWatcher会检测每一个添加到它上面的路径,添加到其上的文件的路径可以使用files()来获取,目录的路径可以使用directories()函数来获取。
  当文件被修改、重命名时或者移除后,会发射fileChanged()信号。相似的,当目录或者它的内容被修改或者移除后,会发射directorychanged()信号。需要注意的是,当文件被重命名或者移除后,或者当目录被移除后,QFileSystemWatcher都会停止监视。

文本流和数据流

使用文本流读/写文本文件

  QTextStream类提供了一个方便的接口来读/写文本,可以在QIODevice、QByteArray和QString上进行操作。使用QTextStream的流操作符,可以方便地读/写单词、行和数字。对于生成文本,QTextStream对字段填充、对齐和数字格式提供了格式选项支持。
  QTextStream提供的格式选项可以在该类的帮助文档中进行查看。除了使用QTextStream类的构造函数来设置设备外,还可以使用setDevice()或者setString()来设置QTextStream要操作的设备或者字符串。可以使用seek()来定位到一个只当位置,使用atEnd()判断是否还有可以读取的数据。如果调用了flush()函数,则QTextStream会清空写缓冲中的所有数据,并且调用设备的flush()函数。
  在内部,QTextStream使用了一个基于Unicode的缓冲区,QTextStream使用QTextCodec来自动支持不同的字符集。默认的,使用QTextCodec::codecForLocale()返回的编码来进行读/写,也可以使用setCodec()函数来设置编码。
  使用QTextStream来读取文本文件一般使用3种方式:
  ①调用readLine()或者readAll()进行一块接着一块的读取。
  ②一个单词接着一个单词。QTextStream支持流入到QString、QByteArray和char *缓冲区,单词由空格分开,而且可以自动跳过前导空格。
  ③一个字符接着一个字符。使用QChar或者char类型的流。这种方式经常在解析文件、使用独立的字符编码和行结束语义时用于方便输入处理。可以通过调用skipWhiteSpace()来跳过空格。
  默认的,当从文本流种读取数字时,QTextStream会自动检查数字的基数表示,例如,如果数字以“0x”开头,则它将被假定为十六进制形式;如果以数字1~9开头,那么它将被假定为十进制形式等。也可以使用dec等流操作符或者setIntegerBase()来设置整数基数,从而停止自动检测。

使用二进制读/写二进制数据

  QDataStream类实现了将QIODevice的二进制数据串行化。一个数据流就是一个二进制编码信息流,它完全独立于主机的操作系统、CPU和字节顺序。数据流也可以读/写未编码的原始二进制数据。QDataStream类可以实现C++基本数据类型的串行化,比如char、short、int和char*等。串行化更复杂的数据是通过将数据分别为基本的数据类型来完成的。
  写入到数据流中的每一个条目都是使用一个预定义的格式写入的,这个格式依赖于条目的类型。支持的Qt类型包括QBrush、QColor、QDateTime、QFont、QPixmap、QString、QVariant和很多其他格式,Qt帮助的Serializing Qt Data Types关键字对应的文档中列出了支持数据流的所有Qt类型的完整列表。
  当输入或输出复杂数据类型时,确保使用相同的数据流版本(version())来进行读取和写入是非常重要的。基本的C++数据类型没有这个要求。如果既要实现向前兼容。又要实现向后兼容,则可以在应用程序中对数据流的版本号进行硬编码:stream.setVersion(QDataStream::Qt_4_0);
  如果是使用一个新的二进制数据格式,例如,在自己应用程序中创建的一个文档的文件格式,这就需要在数据流的前面写入一个简短的数据头,包含了一个magic number(幻数魔数,用来标志文件格式的常数)和一个版本号。
  可以在串行化数据时选择使用哪种字节顺序,默认的设置是大端(MSB在前),改为小端会破坏可移植性(除非读取时也改变为小端)。也可以直接向数据流写入和读取原始二进制数据,可以使用readRawData()将数据从数据流中读取到一个预先分配的char *中,同样,可以使用writeRawData()将数据写入到数据流。注意,需要自己完成对数据的解码和编码。

其他相关类

应用程序设置

  QSettings类提供了持久的、与平台无关的应用程序设置。用户通常期望应用程序可以记住它们的设置,比如窗口大小和位置等。 这些信息在Windows上一般被存储在系统注册表中;在Mas OS X上存储在XML偏好文件中;在Unix系统中,大多数应用程序使用INI文本文件。QSettings是对这些技术的一个抽象,可以使用一种可移植的方式来保存和恢复应用程序的设置。它也支持自定义存储类型。QSettings的API是基于QVariant的,可以用来保存大多数的基于值得类型,如QString、QRect和QImage等。

统一资源定位符

  QUrl类提供了一个方便地接口来操作URLs,URL是Uniform Resource Locator的缩写,被称为统一资源定位符或者网页网址,一个URL的标准格式如下:protocol : //hostname[:port]/path/[?query]#fragment
  其中protocol用来指定传输协议,比如http,ftp等;hostname用来指定存放资源的服务器域名系统主机名或者IP地址,主机名前面还可以包含连接到服务器所需要的用户名和密码;port用来指定端口号,可选,省略时使用默认的端口号,比如http默认端口号是80;path用来指定主机上的目录或者文件地址,路径中可以使用“/”分隔符;query用来设置查询参数,可选,参数间使用“&”符号隔开,fragment用来指定网络资源的片段。
  QUrl可以解析和构建编码或者未编码格式的URL,它也支持国际化域名(IDNs)。可以在构造函数中传递一个QString来初始化QUrl,或者使用setUrl()和setEncodedUrl()。URL可以被表示为两种格式:编码和未编码。未编码的格式适合向用户展示,而编码格式一般用于发送到web服务器。一个URL也可以被一部分一部分地进行构造,可以使用setScheme()来设置协议,使用setUserName()设置用户名;使用setPassword()来设置密码;使用setHost()来设置主机;使用setPort()来设置端口;使用setPath()来设置路径,使用setEncodedQuery()来设置查询字符串;使用setFragment()来设置片段;还可以使用一些方便的函数来进行设置,如setAuthority()可以一次性设置用户名、密码、主机和端口;setUserInfo()可以一次性设置用户名和密码。

Qt资源

  QResource类提供了接口来直接读取资源文件。QResouce用来表示一组数据地对象,该组对象涉及了一个单一的资源实体。QResouce可以使用原始的格式来直接访问字节,这种直接访问允许不适用缓冲复制。QResouce背后的数据和它的孩子通常被编译成一个应用程序库,也可以在运行时加载一个资源;当在运行中进行加载时,资源文件会作为一个很大的数据集进行加载,然后通过引用资源树进行分块输出。
  QResouce也可以使用一个绝对路径进行加载,绝对路径可以使用文件系统的表示法,以一个“/”字符开始;或者使用资源表示法,以“:”字符开始。QResource代表的文件中的数据可以使用qCompress()来进行压缩,对应的使用qUncompress()来进行解压缩。
  一个资源可以留在一个应用程序的二进制文件外面,运行需要时再使用registerResource()进行加载,传递给registerResouce()的资源文件必须是rcc生成的二进制资源。

缓冲区

  QBuffer类为一个QByteArray提供了一个QIODevice接口,它允许使用QIODevice接口来访问QByteArray,这里QByteArray被视为一个标准的随机访问的文件。默认的,创建一个QBuffer时,则自动在内部创建一个QByteArray缓冲区,可以直接调用buffer()来访问这个缓冲区,也可以调用setBuffer()来使用现有的QByteArray,或者向QBuffer的构造函数中传递一个QByteArray。
  调用open()函数打开一个缓冲区,然后使用write()或者putChar()对缓冲区进行写入,使用read()、readLine()、readAll()或者getChar()来读取它。size()函数可以返回缓冲区的当前大小,可以使用seek()函数定位到缓冲区的一个指定位置,最后结束访问缓冲区时要调用close()函数。
  当有新的数据到达了缓冲区时,QBuffer会发射readRead()信号。通过关联这个信号,可以使用QBuffer来存储临时的数据,而后再对它们进行处理。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于QT绘图系统,我可以为您提供一些基本的介绍和使用方法。 QT提供了一套强大的绘图系统,可以用来绘制各种图形、图表、文本、图像等等。QT的绘图系统主要由以下几个类组成: 1. QPainter:绘图类,用于绘制各种图形、图像、文本等。 2. QPen:画笔类,用于设置绘图的线条样式、颜色、粗细等。 3. QBrush:画刷类,用于设置绘图的填充样式、颜色等。 4. QFont:字体类,用于设置绘图的字体、大小、样式等。 5. QRect和QRectF:矩形类,用于表示矩形区域的位置和大小。 6. QImage:图像类,用于表示位图图像。 使用QT绘图系统进行绘图主要有两种方式,一种是在QWidget或QGraphicsView等控件的paintEvent事件中进行绘制,另一种是创建QPixmap或QImage等图像对象,然后使用QPainter在图像上进行绘制。 下面是一个简单的示例代码,演示了如何在QWidget中使用QT绘图系统进行绘制: ```cpp void MyWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); // 设置画笔和画刷 QPen pen(Qt::red, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); QBrush brush(Qt::yellow, Qt::SolidPattern); painter.setPen(pen); painter.setBrush(brush); // 绘制矩形和椭圆 QRect rect(100, 100, 200, 100); painter.drawRect(rect); painter.drawEllipse(rect); // 绘制文本 QFont font("Arial", 20); painter.setFont(font); painter.drawText(rect, Qt::AlignCenter, "Hello, QT!"); } ``` 在这个示例代码中,我们在QWidget的paintEvent事件中创建了一个QPainter对象,然后设置了画笔和画刷,接着使用QRect定义了一个矩形区域,并使用drawRect和drawEllipse方法在该区域上绘制了矩形和椭圆。最后,使用setFont和drawText方法在矩形区域中央绘制了一段文本。 当然,QT绘图系统的功能远不止于此,您可以根据需要使用更多的API进行绘制。希望这个简单的介绍可以帮助您更好地了解和使用QT的绘图系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值