QT学习:10 IO类
title: framework-cpp-qt-10-IO类
EntryName: framework-cpp-qt-10-QIODevice
date: 2020-04-17 10:24:06
categories:
tags:
- qt
- c/c++
---
章节描述:
QIODevice类是所有输入输出IO类的基础类,为IO类提供了统一的调用接口(因此我们称QIODevice类以及其派生类为IO类)。
QIODevice 是一个抽象类,所以不能被实例化,但通常会用到它定义的接口,这些接口提供设备无关的I/O特性。例如Qt的XML类通过操作一个QIODevice 的指针,可以使用各种各样的设备(files,buffers等)。
IO设备类型
IO类支持随机存储,和顺序储存设备。
可以使用
isSequential()判断设备是否是顺序设备。其中顺序设备不支持
pos(),size()方法。调用
size()函数时,如果是随机设备则返回当前设备的大小,如果是顺序设备则返回bytesAvailable()。在设备关闭的情况下调用size()函数将不会反映设备的实际大小,因此调用该函数前保证设备已打开。
顺序存取设备:只能从头开始顺序读写数据,不能指定数据的读写位置。顺序设备没有位置概念,也不支持搜索,只能在数据可用时一次性读取所有数据。典型的顺序设备是Socket
随机存取设备:随机设备就是文件,它们具有大小和当前位置,支持在数据流中向前向后搜索,可以定位到任意位置进行数据的读写。
QT中IO设备的继承类图:
QIODevice
│ 随机设备
├── QBuffer
├── QFileDevice
│ ├── QFile
│ │ └── QTemporaryFile
│ └── QSaveFile
│
│ 顺序设备
├── QAbstractSocket
│ ├── QTcpSocket
│ │ ├── QSctpSocket
│ │ └── QSslSocket
│ └── QUdpSocket
└── QProcess
IO类继承于QIODevice类,只需要实现自己的writeData()和readData()方法。其他读写方法QIODevice都是调用writeData() 和readData()实现的。
操作流程
在访问设备之前,必须先调用open(),并设置正确的OpenMode(such as ReadOnly or ReadWrite)。你可以用write(),putChar()来写入设备。也可以用read(),readLine()来读设备。使用完毕后调用close()。
在访问IO类,必须先调用open()方法打开设备,之后才能调用读写方法对类进行操作。结束操作后需要调用close()方法关闭设备。
调度 与 同步
IO类发射readyRead()信号表示有数据可以读取,对应的可以调用bytesAvailable()方法了解可以读取多少字节的数据。
同理,发射bytesWritten()信号表示数据写入完成,对应的可以调用bytesToWrite()方法了解写入了多少字节的数据。
IO类的读写函数是非阻塞的,调用方法后不会等待数据读写完成方法,而是立即返回。
QTcpSocket and QProcess是QIODevice的子类,是异步的,这意味着 I/O 函数
write()orread()的结果总是立即返回,然而,当控件返回到事件循环时,可能会发生与设备本身的通信。
因此QIODevice提供函数在阻塞调用线程和不输入事件循环的同时,允许程序立即执行,这使得QIODevice的子类可以被使用,在没有循环事件或者是单线程的条件下,提供了waitForReadyRead()和 waitForBytesWriten()方法实现阻塞(在调用读写方法后调用对应的wait…方法实现阻塞)
waitFor...():子类会实现相应的函数为了特殊的操作。
比如QProcess 有个叫waitForStarted()的函数。它将会延迟调用的线程,直到那个process已经启动。
QProcess gzip;
gzip.start("gzip", QStringList() << "-c");
if (!gzip.waitForStarted())
return false; gzip.write("uncompressed data"); QByteArray compressed;
while (gzip.waitForReadyRead())
compressed += gzip.readAll();
IO类例如QFile,QTcpSocket提供了buffer机制,用于减少底层驱动系统调用,提高访问速度。特别是提高了getChar,putChar方法的速度 。但是在多对象需要读取同一个设备的大批量数据时,buffer会导致内存中存在多个同样的数据副本,内存开销巨大。这个情况,可以 在调用open()方法时设置Unbuffered模式关闭buffer机制。
常用操作
open(OpenMode mode):打开设备。mode参数用于设置读写模式,buffer机制,读写机制等。
close():关闭设备
isOpen():判断设备是否被打开。
isWriteable:判断设备是否支持写入模式。(Open方法设置的)
isReadable:判断设备是否支持读取。
isSequential():判断设备是否是顺序设备
isTextModeEnable():Text模式getChar方法将忽略’/r’换行符,返回下个字符。
setTextModeEnable():设置text模式
打开文件
bool QIODevice::open(QIODevice::OpenMode mode)
描述:以指定的方式打开一个文件。
参数解析:
mode:打开方式
QIODevice::NotOpen不打开QIODevice::ReadOnly以只读的方式打开.QIODevice::WriteOnly以只写的方式打开,该模式意味着Truncate,除非与ReadOnly,Append或NewOnly结合使用。QIODevice::ReadWrite设备以读写的方式打开,写入文件会覆盖之前的内容(打开文件期间多次写入不会覆盖)。QIODevice::Append以追加模式打开,以便将所有数据写入文件末尾,此模式下不能读文件。QIODevice::Truncate如果可能,删除文件原有内容。QIODevice::Text读取时,行尾终止符被转换为'\ n'。 写入时,行尾终止符将转换为本地编码,例如Win32的“\ r \ n”。(常用于文本文件以行为单位的读取)QIODevice::Unbuffered无缓冲的形式打开,设备中的任何缓冲都会被跳过。NewOnly:只允许打开一个不存在的文件ExistingOnly:只允许打开一个已经存在的文件
设置
调用openMode()函数可以获取当前设备的打开模式。如果在设备打开的情况下改变设备模式,可以调用setOpenMode()函数来更改。
调用setTextModelEnabled()函数可以设置设备模式为Text,这对于自定义处理终止符非常有帮助。调用isTextmodeEnabled()函数可以确定设备模式是否有Text。
读取
读取数据前必须先判断是否有数据可读,有两种方法来确定是否可以读取数据:
调用
isReadable()函数;接收到
readyRead()信号。(当有新数据可被读取时会发出该信号)
通常采用信号的方式,然后调用
bytesAvailable()函数来确定可读取数据的大小,通常与顺序设备一起使用,来确定缓冲区中分配的字节数。
调用read()函数来读取数据,无法读取时返回-1。
便捷函数有readAll()、readLine()/canReadLine()、getChar()/ungetChar()。
写入
调用isWritable()函数可以判断设备是否设置打开模式中包含了WriteOnly标志,这是一个便捷函数。
写入数据时,一般会先写入缓冲区,然后再从缓冲区写入设备。调用bytesToWrite()函数返回即将写入设备的数据大小,而对于无缓冲的设备则返回0。每次写入设备数据时都会发出bytesWritten()信号。
写入数据到设备中,调用write()函数:
qint64 QIODevice::write(const char *data)
qint64 QIODevice::write(const QByteArray &byteArray)
qint64 QIODevice::write(const char *data, qint64 maxSize)
便捷函数有putChar()函数。
读写位置
对于随机设备来说,每次读写都会导致内部的文件指针偏移;只有随机设备才可以设置/读取读写位置。
bool QIODevice::seek(qint64 pos) //定位文件指针。
qint64 QIODevice::pos() const // 获取文件指针位置
事务机制
事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据项的一个程序执行单元(unit)。事务一般由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
为什么要事务?
事务是为解决数据安全操作提出的,事务控制实际上就是控制数据的安全访问。
用一个简单例子说明:银行转帐业务,账户A要将自己账户上的1000元转到B账户下面,A账户余额首先要减去1000元,然后B账户要增加1000元。假如在中间网络出现了问题,A账户减去1000元已经结束,B因为网络中断而操作失败,那么整个业务失败,必须做出控制,要求A账户转帐业务撤销。这才能保证业务的正确性,完成这个操走就需要事务,将A账户资金减少和B账户资金增加放到同一个事务里,要么全部执行成功,要么全部撤销,这样就保证了数据的安全性。
事务的4个特性(ACID):
原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。
一致性(consistency):事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。(实例:转账,两个账户余额相加,值不变。)
隔离性(isolation):一个事务的执行不能被其他事务所影响。
持久性(durability):一个事务一旦提交,事物的操作便永久性的保存在DB中。即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
一般来说,异步设备的输入流是分段的,数据块可以在任意的时间内到达。要在这种情况下读到完整数据,使用QIODevice的事务机制。
读取设备中的数据时,我们可以调用startTransaction()函数来在读取操作序列中设置一个恢复点。接下来的代码进行一般的读取操作,然后调用commitTransaction()函数来提交所有的操作。例如:
in.startTransaction();
QString nextFortune;
in >> nextFortune;
if (!in.commitTransaction())
return;
调用rollbackTransaction()函数来回滚事务,这会将来自源的输入流恢复到startTransaction()时的点。
读写通道
一些顺序设备支持多通道通信,这些通道代表了具有独立排序传递特性的独立数据流。打开设备后,调用readChannelCount()、writeChannelCount()函数来确定通道数。调用setCurrentReadChannel()、setCurrentWriteChannel()函数来切换通道。
此外,QIODevice还提供额外的信号来处理通道的异步通信。
如果通道有新数据可被设备读取时,发出
channelReadyRead()信号。如果通道有数据写入设备时,发出
channelBytesWritten()信号。关闭读取通道禁止输入流时,会发出
readChannelFinished()信号。
错误信息
当设备发生故障时,我们可以调用setErrorString()函数来给设备设置一个错误信息,任何时候都可以调用errorString()函数来查看当前设备的错误信息。
QT学习:10 IO类的更多相关文章
- QT学习之常用类的总结
QApplication 应用程序类 管理图形用户界面应用程序的控制流和主要设置 QPalate QLabel 标签类 提供文本或者图像的显示 QPushButton 按钮类 提供 ...
- QT学习之QPair类
#QPair类 QPair是一个用来存储一对对象的容器模板.其有两个值,first和second. QPair() QPair(const T1 & value1, const T2 & ...
- Qt 学习之路 2(10):对象模型
Home / Qt 学习之路 2 / Qt 学习之路 2(10):对象模型 Qt 学习之路 2(10):对象模型 豆子 2012年9月2日 Qt 学习之路 2 45条评论 标准 C++ 对象模 ...
- Java程序猿的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
- Qt 学习之路 2(73):Qt 线程相关类
Home / Qt 学习之路 2 / Qt 学习之路 2(73):Qt 线程相关类 Qt 学习之路 2(73):Qt 线程相关类 豆子 2013年11月26日 Qt 学习之路 2 7条评论 希 ...
- QT学习之文件系统读写类
#QT学习之文件系统读写类 QIODevice QFileDevice QBuffer QProcess 和 QProcessEnvironment QFileDevice QFile QFileIn ...
- 系统学习 Java IO (十六)----这么多类,应该用哪个?
目录:系统学习 Java IO---- 目录,概览 Java IO目的和功能 Java IO 包含 InputStream,OutputStream,Reader 和 Writer 类的许多子类. 原 ...
- iOS学习10之OC类和对象
本次是OC的第一节课,主要是学习和理解类与对象 1.面向对象 1> OOP(Object Oriented Programming)面向对象编程. 面向对象以事物为中心,完成某件事情都需要哪些事 ...
- Qt 学习之路 :Qt 线程相关类
希望上一章有关事件循环的内容还没有把你绕晕.本章将重新回到有关线程的相关内容上面来.在前面的章节我们了解了有关QThread类的简单使用.不过,Qt 提供的有关线程的类可不那么简单,否则的话我们也没必 ...
- QT学习之第一个程序
QT学习之第一个程序 目录 手动创建主窗口 居中显示 添加窗口图标 显示提示文本 Message Box的应用 手动连接信号与槽 手动创建主窗口 窗口类型 QMainWindow: 可以包含菜单栏.工 ...
随机推荐
- 实验1 在MAX10 FPGA上实现组合逻辑
实验1 在MAX10 FPGA上实现组合逻辑 实验前的准备工作:参照讲义步骤安装Quartus,Modelsim和System Builder.阅读材料:1)推荐的文件组织形式:2)Verilog 1 ...
- CRAPS赌博小游戏
游戏规则 代码实现 首先把这个规则用代码写出来 再在它基础上进行简单的可视化(主要是利用Easygui的界面) 最后查缺补漏,看看有没有什么Bug 利用pyinstaller -F -w -i xx. ...
- NumPy 数组创建方法与索引访问详解
NumPy 创建数组 NumPy 中的核心数据结构是 ndarray,它代表多维数组.NumPy 提供了多种方法来创建 ndarray 对象,包括: 使用 array() 函数 array() 函数是 ...
- golang url解析
package main import "fmt" import "net/url" import "strings" func main( ...
- MindSpore反向传播配置关键字参数
技术背景 在MindSpore深度学习框架中,我们可以向construct函数传输必备参数或者关键字参数,这跟普通的Python函数没有什么区别.但是对于MindSpore中的自定义反向传播bprop ...
- pageoffice6 版本实现在线打开word 文件禁止保存、禁止另存、禁止打印的需求
在实际项目需求中,有时需要限制用户的保存.另存.打印文件操作,实现此效果只需在OnPageOfficeCtrlInit或AfterDocumentOpened事件中调用js设置PageOffice控件 ...
- AIRIOT答疑第1期 | 零开发基础也能干物联网平台项目?
当然可以! 物联网低代码平台以零门槛.部署快.灵活性高.满足二次开发等特点,成为近两年来IOT服务的生力军.项目团队即使没有研发人员,也可以像拼乐高一样快速搭建物联网平台,功能全面,满足多数业务场景下 ...
- Python:解决Matplotlib保存图片显示不全问题
保存图片的时候设置参数bbox_inches = 'tight',如: plt.savefig("Matplotlib/graph.png", bbox_inches = 'tig ...
- 继承与ER图
会员是用户吗? 实体与集合 er图叫实体联系图.什么是实体?是现实中存在的事物个体,用户背后是实际存在的单个人. 对象->实体 类->实体的集合 er图描述的是实体间的联系 会员是真实存在 ...
- zabbix笔记_001
zabbix介绍 zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管 ...