Qt学习笔记(八)输入与输出

Qt通过QIODevice为输入输出提供了极佳的支持。QIODevice是一个封装能够读写字节块”设备“的强有力的提取器。QT包括如下QIODevice子类:

QFile :在本地文件系统和嵌入式资源中存取文件

QTemporaryFile:在本地文件系统中创建并存取临时文件

QBuffer:从QByteArray中读取或者写入数据

QProcess:运行外部程序并处理进程间通信

QTcpSocket:利用TCP在网络上传输数据流

QUdpSocket:在网络上发送或接受UDP数据报

QSslSocket:利用SSL/TLS在网络上传输加密数据流

QProcess、QTcpSocket、QUdpSocket和QSslSocket都是顺序存储设备,这意味着所存储的数据从第一个字节开始到最后一个字节为止只能被读取一次。QFile、QTemporaryFile、QBuffer则是随机存储设备,可以从任意位置多次读取字节位所存储的数据。这些随机存取设备还提供了QIODevice::seek()函数以重新配置文件的指针。

除了设备类,Qt还提供了两个更高级的流类,使得可以从任意的输入输出设备读取或写入数据:QDataStream用来读写二进制数据;QTextStream用来读写文本数据。这些类考虑了诸如字节顺序和文本编码等问题,以保证运行在不同平台或者不同语言环境下的Qt应用程序可以相互读写文件。

QFile使得存取单个文件很方便,不论是在文件系统中还是作为资源嵌入在应用程序的可执行文件中。对于需要依靠整个文件组集一同运作的应用程序,Qt提供了QDir和QFileInfo类,他们分别用于处理目录地址和提供内部文件信息。

QProcess类允许启动外部程序并通过标准输入、输出以及标准错误通道(cin, cout, cerr)与外部程序交互,可以设置外部程序的环境变量和工作目录。在默认情况下,交互的执行过程是异步的(不阻塞的),但是不排除在某些操作上发生阻塞的可能。


文本文件与二进制文件的定义

    大家都知道计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等等。二进制文件是基于值编码的文件,你可以根据具体应用,指定某个值是什么意思(这样一个过程,可以看作是自定义编码。

    从上面可以看出文本文件基本上是定长编码的(也有非定长的编码如UTF-8)。而二进制文件可看成是变长编码的,因为是值编码嘛,多少个比特代表一个值,完全由你决定。大家可能对BMP文件比较熟悉,就拿它举例子吧,其头部是较为固定长度的文件头信息,前2字节用来记录文件为BMP格式,接下来的8个字节用来记录文件长度,再接下来的4字节用来记录bmp文件头的长度。

对二进制和文本文件的数据操作的最小单位为字节(8bit),虽然在二进制文件中甚至一个比特都有可能代表具体信息,但在高级语言编程实现的时候,一般都用基本的数据类型(如int,double, char等,比特位数为8的倍数)。即二进制可以按照char,int,double等类型读写,而文本只能按照char类型读取。

记事本无论打开什么文件都按既定的字符编码工作(如ASCII码),所以当他打开二进制文件时,出现乱码也是很必然的一件事情了,解码和译码不对应嘛。例如文件流''00000000_00000000_00000000_00000001''可能在二进制文件中对应的是一个四字节的整数int 1,在记事本里解释就变成了"NULL_NULL_NULL_SOH"这四个控制符。


读取和写入二进制数据

在QT中载入和保存二进制数据的最简单方式是通过实例化一个QFile打开文件,然后通过QDataStream对象存取它。QDataStream提供了一种与运行平台无关的存储格式。例如在一个名为facts.dat的文件中存储一个整型数据、一个QImage以及一个QMap<QString, QColor>的代码:

QImage image("philip.png");

QMap<QString, QColor> map;

map.insert("red", Qt::red);

map.insert("green", Qt::green);

map.insert("blue", Qt::blue);

QFile file("facts.dat");

if ( !file.open(QIODevice::WriteOnly))

{

std::cerr << "Cannot open file for writing : " << qPrintable(file.errorString()) << std::endl;

return;

}

QDataStream  out(&file);

out.serVersion(QDataStream::Qt_4_3);  //设置Qt_4_3版本号

out << quint32(0x12345678 ) << image << map; //先写入数字0x12345678 ,作为特征值

为了确保数字 0x12345678在所有平台上都是按照无符号32位整数形式写入,将它强制转换为quint32, 这是一个严格保证为32位的数据类型。为了保证互通性,QDataStream会默认高字节在后的大尾方式存储,这可以通过调用setByteOrder()来改变。

//从facts.dat文件中读回数据

quint32   n;

QImage image;

QMap<QString, QColor> map;

QFile file("facts.dat");

if ( !  file.open(QIODevice::ReadOnly)

{

std::cerr << "Cannot open file for reading : " << qPrintable(file.errorString()) << std::endl;

return;

}

QDataStream in(&file);

in.setVersion(QDataStream::Qt_4_3);

in >> n >> image >> map;

利用readRawBytes()和writeRawBytes(), QDataStream也可以用来读写一些原始的二进制数据而不需要任何的字节计数首部。当从QDataStream读取数据时,错误处理相当容易。流有一个status()值,可以是QDataStream::Ok, QDataStream::ReadPastEnd, QDataStream::ReadCorruptData.如果错误发生,>>操作符总是读取0值或空值。这表示通常可以简单的读取一个文件而不用担心出错,并在最后检查status()值检查读取的文件数据是否有效。

对于自定义的数据类型,也可以通过重载 << >>操作符的形式,来进行使用<<, >>操作符很方便的读取写入:

class Painting 

{

xxx

xxxx

}

QDataStream &operator << (QDataStream &out, const Painting &painting)

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值