扫描器的高效实现(二)

2014-11-24 02:08:35 · 作者: · 浏览: 1
只是这里每次加载BUFLEN个1字节数据块。
#define BUFLEN 80
int lineLen=0;
int readPos=-1;
char line[BUFLEN];
static int offset=0;//记录文件指针的偏移,每次打开文件需要初始化为0
char scan(FILE*file)
{
if(readPos==lineLen-1)//缓冲区读取完毕
{
lineLen=fread(line,BUFLEN,1,file);//重新加载缓冲区数据
if(lineLen){//成功加载
offset+=BUFLEN;//累计偏移
lineLen=BUFLEN*1;
}
else{//最后一段不足BUFLEN,无法获取读取的长度
fseek(file,offset,SEEK_SET);//撤回文件指针
lineLen=fread(line,1,BUFLEN,file);//按字节重读最后一段
line[lineLen++]=-1;//文件结束标记
}
lineLen=pos;//记录缓冲区长度
readPos=-1;//恢复读取位置
}
readPos++;//移动读取点
return line[readPos]; //获取新的字符
}
测试代码的执行时间。
次数
1
2
3
4
5
平均值
real
2241
2223
2259
2223
2221
2233.4
user
620
540
616
600
648
604.8
sys
1616
1680
1640
1620
1568
1624.8
计算代码的CPU平均执行时间为604.8+1624.8=2229.6ms,这有点出乎意料。分析原因,可能是因为文件较小时,当读取到最后一块缓冲区时,撤回文件指针比较消耗时间。因此,使用方法三实现的扫描器性能更稳定,且代码更简洁。
(5)如果使用fread不是读入1个BUFLEN字节数据,而是读取BUFLEN/2个2字节数据,那么最后一次将读入最后一个字节。
#define BUFLEN 80
int lineLen=0;
int readPos=-1;
char line[BUFLEN];
char scan(FILE*file)
{
if(readPos==lineLen-1)//缓冲区读取完毕
{
lineLen=fread(line,2,BUFLEN/2,file);//重新加载缓冲区数据
if(lineLen){//成功加载
lineLen=lineLen*2;//读取了偶数字节
}
else{//最后一字节已经存储在line[0]
line[1]=-1;//文件结束标记
lineLen=2;//长度
}
lineLen=pos;//记录缓冲区长度
readPos=-1;//恢复读取位置
}
readPos++;//移动读取点
return line[readPos]; //获取新的字符
}
测试代码的执行时间。
次数
1
2
3
4
5
平均值
real
663
657
646
665
659
658
user
208
224
204
212
184
206.4
sys
452
428
440
456
472
449.6
计算代码的CPU平均执行时间为206.4+449.6=656ms。虽然该方法不需要撤回文件指针,但是性能仍不如方法三。
综上所述,方法三是实现扫描器比较高效的方式:使用缓冲区代替文件的频繁访问,并在缓冲区读取完毕时,使用fread每次加载BUFLEN个1字节数据块更新缓冲区数据。希望本文对你有所帮助。