文件流的刷新和定位
1. 文件指针的基本概念在C语言文件操作中每个打开的文件都有一个文件指针file pointer它指向文件中当前读写的位置。理解文件指针的行为是掌握文件操作的关键。文件指针的特点打开文件时指针默认在文件开头0字节处每次读写操作后指针会自动移动到下一个位置写入操作完成后指针停留在文件末尾需要手动管理指针位置才能实现灵活的文件访问常见问题文件写完后文件指针指向文件末尾如果这时候读读不出来内容。解决办法移动指针到文件头使用fseek()或rewind()关闭文件重新打开2. fflush() - 刷新文件缓冲区功能将流缓冲区中的数据写入实际的文件或设备。原型intfflush(FILE*stream);参数stream指向FILE结构的指针指定要刷新的文件流返回值成功返回0失败返回EOF通常是-1Linux下的特殊行为只能刷新输出缓冲区输入缓冲区会被丢弃fflush(stdin)的行为未定义不建议使用使用场景确保数据持久化在关键数据写入后立即刷新防止程序崩溃导致数据丢失实时输出标准输出(stdout)刷新确保立即显示内容文件同步在多进程/多线程环境中确保文件状态一致示例#includestdio.hintmain(){FILE*fpfopen(data.txt,w);if(fpNULL){perror(打开文件失败);return1;}// 写入重要数据fprintf(fp,重要数据%d\n,100);// 立即刷新缓冲区确保数据写入磁盘if(fflush(fp)!0){perror(刷新缓冲区失败);}// 继续写入其他数据fprintf(fp,更多数据%s\n,test);fclose(fp);return0;}3. ftell() - 获取当前文件位置功能返回文件指针的当前位置相对于文件开头的字节偏移量。原型longftell(FILE*stream);参数stream指向FILE结构的指针返回值成功返回当前位置字节偏移量失败返回-1L示例#includestdio.hintmain(){FILE*fpfopen(example.txt,r);if(fpNULL){perror(打开文件失败);return1;}// 写入一些数据fprintf(fp,Hello, World!\n);fprintf(fp,This is a test.\n);// 获取当前位置longpositionftell(fp);printf(当前文件位置%ld 字节\n,position);// 移动到文件开头fseek(fp,0,SEEK_SET);printf(移动后位置%ld 字节\n,ftell(fp));fclose(fp);return0;}4. fseek() - 移动文件指针功能设置文件指针的位置。原型intfseek(FILE*stream,longoffset,intwhence);参数stream文件流指针offset偏移量字节数可正可负whence起始位置取以下值之一SEEK_SET0从文件开头开始SEEK_CUR1从当前位置开始SEEK_END2从文件末尾开始返回值成功返回0失败返回非0值whence参数详解SEEK_SET从距文件开头 offset 位移量为新的读写位置SEEK_CUR以目前的读写位置往后增加 offset 个位移量SEEK_END将读写位置指向文件尾后再增加 offset 个位移量常用操作// 移动到文件开头fseek(fp,0,SEEK_SET);// 移动到文件末尾fseek(fp,0,SEEK_END);// 从当前位置向后移动10字节fseek(fp,10,SEEK_CUR);// 从文件末尾向前移动5字节fseek(fp,-5,SEEK_END);完整示例#includestdio.hintmain(){FILE*fpfopen(data.bin,wb);if(fpNULL){perror(打开文件失败);return1;}// 写入数据intdata[]{10,20,30,40,50};fwrite(data,sizeof(int),5,fp);// 获取文件大小fseek(fp,0,SEEK_END);longfile_sizeftell(fp);printf(文件大小%ld 字节\n,file_size);// 读取第三个整数跳过前2个fseek(fp,2*sizeof(int),SEEK_SET);intthird_value;fread(third_value,sizeof(int),1,fp);printf(第三个值%d\n,third_value);// 修改第四个值fseek(fp,3*sizeof(int),SEEK_SET);intnew_value99;fwrite(new_value,sizeof(int),1,fp);fclose(fp);return0;}5. rewind() - 重置文件指针到开头功能将文件指针重置到文件开头相当于fseek(fp, 0, SEEK_SET)。原型voidrewind(FILE*stream);特点无返回值同时清除文件错误标志比fseek(fp, 0, SEEK_SET)更简洁示例#includestdio.hintmain(){FILE*fpfopen(text.txt,r);if(fpNULL){perror(打开文件失败);return1;}// 写入内容fprintf(fp,第一行内容\n);fprintf(fp,第二行内容\n);// 此时指针在文件末尾printf(写入后位置%ld\n,ftell(fp));// 使用 rewind 重置指针rewind(fp);printf(rewind后位置%ld\n,ftell(fp));// 读取文件内容charbuffer[100];while(fgets(buffer,sizeof(buffer),fp)!NULL){printf(读取%s,buffer);}fclose(fp);return0;}6. 注意事项与限制6.1 重要注意事项文件的打开使用 “a” 模式时fseek() 无效以追加模式(“a或a”)打开的文件所有写入操作都会自动定位到文件末尾即使使用fseek()移动了指针写入时仍会自动回到文件末尾rewind(fp) 相当于 fseek(fp, 0, SEEK_SET)但rewind()还会清除文件错误标志fseek()不会清除错误标志文件大小限制ftell()、fseek()、rewind()这三个函数只适用于2GB以下的文件对于大文件应使用ftello()、fseeko()等64位版本如果系统支持6.2 文本文件与二进制文件的区别文本文件换行符可能被转换Windows: \r\n, Linux: \nftell()返回的值可能不能直接用于fseek()建议使用文本模式进行读写二进制文件数据按原样读写无转换ftell()返回的字节偏移量可直接用于fseek()适合处理非文本数据7. 函数对比与选择指南函数功能返回值常用场景fflush()刷新缓冲区到磁盘成功0失败EOF关键数据持久化、实时输出ftell()获取当前文件位置字节偏移量失败-1L记录位置、计算文件大小fseek()移动文件指针成功0失败≠0随机访问、定位读写rewind()重置指针到开头无重新读取文件、清除错误标志