Qt流缓冲的刷新时间小解

今天用QTextStream时候遇到了点点小问题,就是在写入的时候,发现移动文件指针不会覆盖后面的数据。今天一天的时间基本上都放在了这个问题上面,下面具体说说。

例如下面的例子

QFile file(“c:/1.txt”);

QTextStream text(&file);

file.open(QFile::Write);

text<<”1”<<”2”;

text.device().seek(0);

text<<”3”;

其它代码略。下面执行了下面的代码后,文件显示的内容为:123,而不是我们希望的32,这说明了seek(0)并没有移动了文件指针,这到底是怎么回事呢?又如下面的代码

QFile file(“c:/2.txt”);

QTextStream text(&file);

file.open(QFile::Read);

QString str;

text>>Str;

qDebug()<<str;

text.device().seek(0);

str.clear();

str=text.readAll();

qDebug()<<str;

执行后会发现并不是想象的那样,输出了第一行的字符串后,输出余下的,而是输出了余下的后,再输出全部的内容,这又是怎么回事呢?

写了一下午和晚上的代码进行反复的验证,下面是得出的结论:

首先,对于QTextStream类来说,该类有个BUFFER,就是缓冲区,当我们向它绑定的IOdevice写入或者读取数据时候,不会直接操作device,而是操作缓冲区,这样做有个好处,避免频繁的写入硬盘,毕竟内存的速度比硬盘快多了。Qt就是这样,QTextStream会将数据先存入缓冲区,在缓冲区操作,从而节省了系统资源。如第一个例子,text绑定了1.txt,第一个写入语句并没有直接把内容写入文件中,而是写入了内存中的缓冲区,当然缓冲区有大小,大于某大小后,或者主动进行刷新时候,会将数据写入文件,但是我们的例子内容很少,所以都会读入缓冲区,执行seek时候,file的文件指针的确是移动了,移动到了首行,然后再一次的写入数据到了缓冲区,当主函数执行完毕时候,打开文件,内容是123,下面我们把seek参数改为2(用字为单位),再次执行主函数,会发现文件的内容变成了空格123,所以可以得出一个结论,seek是有效的,但是因为实际写入数据的时刻在seek之后,所以无法满足我们原先的设想。

想实现原先的设想,我们可以直接操作file,所有的操作都是即时的,不受缓冲区刷新的影响。另外,我们可以主动的去刷新缓冲区,在所有<<操作符后加一个<<flush;主动去刷新缓冲区,这样就可以直接把数据写入对象中。

对于第二个例子,其实原理跟第一个差不多。当要读取某个文件时候,当文件的大小小于缓冲区大小限额时候,会将数据全部都读取到缓冲区,并将devicepos到最后,每次通过流来读取文件内容的时候,其实都在缓冲区进行操作,那么我们设置指针其实都与缓冲区无关,因为数据的读取在缓冲区而已。而在读取了一个字符串(数据是一行一行的)之后,我们用了seek(0)函数,之后执行readAll()发现数据是余下的数据和原先的文件中的所有数据,这是为什么呢?

因为缓冲区有一个大小的限额,假如文件太大的话,会先读入一部分到缓冲区,然后设置devicepos为那最后部分,内存中的内容读完后,会返回到原先设置的pos,然后继续读取。明白了这个后,我们就可以很容易的明白为什么会输出那些奇怪的东西了。因为文件实在是太小了,所以全部的读入了内存缓冲区,然后先将第一行的字符串输出到str,同时缓冲区也有一个pos,设置到了第一行的字符串的末尾,末尾还有一个回车。执行readAll()函数时候,会将缓冲区的所有的内容全部输出,也就是回车加上缓冲区的所有内容。那么怎么会出现此文件的全部内容呢?答案是我们设置的seek(0),因为当文件太大的时候不能一次性的读入内存缓冲区,剩下的数据该怎么办?所以会去查找devicepos,看是否到了结尾,正常情况下是到结尾的,有2两种情况:

1.文件能够全部读入内存缓冲区

这个情况很简单,全部读入后直接将pos设置为结尾,这样当readAll()后发现已经到了文件结尾了,结束函数,返回正常值。

2.文件不能全部读入内存缓冲区

这个情况也很简单,读取一部分,并将pos设置为截断的部分,readAll()后发现文件没到结尾,继续读入缓冲区,并输出,直到到了文件结尾。

我们的情况则是读取过程中认为的执行了seek(0),即改变了对象自动设置的pos,这样,当pos检测是否到文件结尾时候,会发现没有到!所以又一次的将文件内容全部读到缓冲区并且输出,所以才会又输出了一次全部内容,然后pos发现到了文件结尾,结束函数。

这样,两个问题都解决了。当然个人能力有限,无法完全明白QIODevice的源码,只能不断的写代码进行测试。另外发现QDataStream输入到Device一次后,就会自动刷新,不用人工去刷新,其实我这个问题是看GUI with QT4TCP部分发现的。

 

 

今天又发现,假如使用QTextStream的pos()函数,会根据device重置流的位置和device的位置,然后清空流。而直接操作device的pos函数直接返回了当前的位置,不会进行任何操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值