1. 文件的顺序读写
1.1 顺序读写函数的介绍
函数名 功能 适用于
fgetc 字符输入函数 所有输入流
fputc 字符输出函数 所有输出流
fgets 文本行输入函数 所有输入流
fputs 文本行输出函数 所有输出流
fscanf 格式化输入函数 所有输入流
fprintf 格式化输出函数 所有输出流
fread 二进制输入 文件输入流
fwrite 二进制输出 文件输出流
上面的适用于所有输入流一般指适用于标准输入流和其他输入流(如文件输入流); 所有输出流一般指适用于标准输出流和其他输出流(如文件输出流)。
1.2 对比一组函数
1.2.1 scanf/fscanf/sscanf
1.2.2 printf/fprintf/sprintf
2. 文件的随机读写
2.1 fseek
根据文件指针的位置和偏移量来定位文件指针(文件内容的光标)
int fseek ( FILE * stream, long int offset, int origin );
例子:
#include<stdio.h>
int main()
{
FILE* pf = fopen("data.txt", "wb");
fputs("This is an apple", pf);
fseek(pf, 9, SEEK_SET);
fputs(" sam", pf);
fclose(pf);
return 0;
}
2.2 ftell
返回文件指针相对于起始位置的偏移量
long int ftell ( FILE * stream );
int main()
{
long size;
FILE* pf = fopen("data.txt", "rb");
if (pf = NULL)
{
perror("Error opening file ");
}
else
{
feek(pf, 0, SEEK_END);
size = ftell(pf);
fclose(pf);
printf("Size of myfile.txt: %ld bytes\n", size);
}
return 0;
}
2.3 rewind
让文件指针位置回到文件的起始位置。
void rewind ( FILE * stream );
int main()
{
int n;
FILE* pf;
char buf[27];
pf = fopen("data.txt", "w+");
for (n = 'A'; n <= 'Z'; n++)
{
fputc(n, pf);
}
rewind(pf);
fread(buf, 1, 26,pf);
fclose(pf);
buf[26] = '\0';
printf("buf");
return 0;
}
3. 文件读取结束的判定
3.1 被错误使用feof
在文件读取过程中,不能使用feof函数的返回值直接判断文件是否结束。
feof的作用是:当文件读取结束的时候,判断读取结束原因是否是:遇到文件末尾结束。
1. 文件读取是否结束,判断返回值为EOF(fgetc),或者NULL(fgets)
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread判断返回值是否小于实际要读的个数。
文本文件例子:
# include <stdio.h># include <stdlib.h>int main ( void ){int c; // 注意: int ,⾮ char ,要求处理 EOFFILE* fp = fopen( "test.txt" , "r" );if (!fp) {perror( "File opening failed" );return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回 EOFwhile ((c = fgetc(fp)) != EOF) // 标准 C I/O 读取⽂件循环{putchar (c);}// 判断是什么原因结束的if (ferror(fp))puts ( "I/O error when reading" );else if (feof(fp))puts ( "End of file reached successfully" );fclose(fp);}
#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{double a[SIZE] = { 1.,2.,3.,4.,5. };FILE* fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组fclose(fp);double b[SIZE];fp = fopen("test.bin", "rb");size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组if (ret_code == SIZE) {puts("Array read successfully, contents: ");for (int n = 0; n < SIZE; ++n)printf("%f ", b[n]);putchar('\n');}else { // error handlingif (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) {perror("Error reading test.bin");}}fclose(fp);
}
4. 文件缓冲区
#include <stdio.h>
#include <windows.h>
//VS2022 WIN11环境测试
int main()
{FILE*pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区printf("睡眠10秒-已经写数据了,打开test.txt⽂件,发现⽂件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘)//注:fflush 在⾼版本的VS上不能使⽤了printf("再睡眠10秒-此时,再次打开test.txt⽂件,⽂件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在关闭⽂件的时候,也会刷新缓冲区pf = NULL;return 0;
}
结论:因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂件。