- 论坛徽章:
- 0
|
本帖最后由 huangzhenfan 于 2012-08-25 00:05 编辑
源码如下:
#include <stdio.h>
struct record
{
char a;
};
int main(void)
{
FILE *fp;
struct record rec;
fp = fopen("testfile.txt", "r+");
if (fp != NULL)
{
while (fread((char *)&rec, sizeof(rec), 1, fp)==1)
{ /* 对rec执行某些操作 */
++rec.a;
if (1/* rec 须被重新写入 */)
{
fseek(fp, -(long)sizeof(rec), 1); /* SEEK_CUR */
fwrite((char *)&rec, sizeof(rec), 1, fp);
fflush(fp); /* 必须要加上这句,或者 fseek(fp, 0, 1); 写操作才能成功 */
}
}
fclose(fp);
return 0;
}
为什么使用fflush(fp),或fseek(fp,0,1)后才能解决死循环,求分析。
我在gcc4.45 和vc2010上测试。得出读写是使用同一个offset的
测试代码如下:
#include <stdio.h>
#include <string.h>
int main (void)
{
FILE *fp;
// 缓冲区buf初始化为0
char buf[1024]={0},tmp[1024]={0};
fp=fopen ("C:\\doubuf.txt","rb+");
// 设置文件fp缓冲区buf,全缓冲,大小为1024字节
setvbuf(fp,buf,_IOFBF,1024);
// fprintf 函数对数据123进行二次处理(即格式化)写入文件:(此时数据被放入缓冲buf)
fprintf (fp,"123 ");
// 查看buf数据
printf ("%d,%c,%c\n",strlen(buf),buf[0],buf[1]);
// 此时fscanf函数执行失败,因为先前数据还没有写入文件
// fscanf(fp,"%s",tmp);
// 刷新缓冲,将数据写入文件,文件位置指针offset到达文件尾。
fflush(fp);
// 文件位置指针offset在文件尾,fscanf函数又一次执行失败。
// fscanf(fp,"%s",tmp);
// 将文件位置指针offset移到距文件开始处0字节。
fseek(fp,0,SEEK_SET);
// 从文件中读取字符串存入tmp数组
fscanf(fp,"%s",tmp);
// 查看tmp数据
printf ("%d,%c,%c\n",strlen(tmp),tmp[0],tmp[1]);
return 0;
}
再对缓冲区跟踪,发现读写使用同一个缓冲区的,并且每隔4个字节后就会刷新缓冲区,我的平台是win7_64,测试环境GCC4.45 VC2010
[/size2]#include <stdlib.h>
#include <stdio.h>
#define print_buf printf ("fp->_base=%p缓冲区基地址\nfp->_ptr=%p指向当前缓冲区内容的指针\nfp->_cnt=%d如果是输入缓冲区就显示现在缓冲区里还有多少个有效数据\nfp->_bufsiz=%d缓冲区总大小\nfp->_file=%d这个是设备句柄\nfp->_flag=%d标志位可写可读的模式\n\n",fp->_base,fp->_ptr,fp->_cnt,fp->_bufsiz,fp->_file,fp->_flag)
int main( void )
{
FILE *fp=NULL;
char buf[4096]={0};
int i = 99 , t ;
fp = fopen("abc", "wb");
fwrite(&i, sizeof(int), 1, fp);
fclose(fp);
fp = fopen("abc", "rb+");
setvbuf (fp,buf,_IOFBF,1024);
while ( fread(&t, sizeof(int), 1, fp) ) // 读一个数放在t中
{
printf ("offset:%lu\n", ftell(fp)); // 读取操作后,查看文件offset
print_buf; // 查看缓冲区信息
fseek(fp,-4 ,SEEK_CUR);//退回原来的位置
fwrite(&i,sizeof i,1,fp) ;// 写入一个整型量i 到文件;
// fflush(fp);
printf ("offset:%lu\n", ftell(fp)); // 写入操作后,查看文件offset
print_buf; // 查看缓冲区信息
system ("pause"); // windows系统按任意键断续观察每次的变化
i = t ;
}
}
望大神门指点
|
|