功能:根据文件指针的位置和偏移量来定位文件指针
参数一:流,从而控制要进行操作的文件
参数二:offset,偏移量,以字节为单位,正数表示正向偏移,负数表示负向
参数三:初始位置,有三种:文件起始点(SEEK_SET)、当下点(SEEK_CUR)、文件末尾(SEEK_END),这三个位置点可以分别被0、1、2代替
返回值:操作成功返回0,操作失败(比如offset超过文件自身大小)返回非0(有的编译器返回-1)
练习1:在data.txt文件中写下abcdefghi,从当下位置SEEK_CUR偏移找到某个字母
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ch = fgetc(pf);
printf("%c\n", ch);//a
ch = fgetc(pf);
printf("%c\n", ch);//b
ch = fgetc(pf);
printf("%c\n", ch);//c
fseek(pf, -3, SEEK_CUR);//SEEK-CUR可用1替代
ch = fgetc(pf);
printf("%c\n", ch);//a
fclose(pf);
pf = NULL;
return 0;
}
操作台显示结果:
练习2:找从data.txt文件末尾位置SEEK_END向前偏移5个得到的字符
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fseek(pf, -5, SEEK_END);
int ch = fgetc(pf);
printf("%c", ch);
fclose(pf);
pf = NULL;
return 0;
}
功能:返回光标在文件中相对于起始位置的偏移量
返回值:成功调用函数时,返回偏移量;调用失败,返回-1L
练习:读取三个字符后返回指针的偏移量(data.txt文件中写着abcdefghi)
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
int pos = ftell(pf);
printf("%d\n", pos);
fclose(pf);
pf = NULL;
return 0;
}
功能:让指针直接回到文件起始位置
让指针直接回到起始位置的另一种方法:用fseek函数,得到从起始点偏移量为0的位置。具体写法:fseek(pf,0,SEEK-SET)
练习:让光标回到文件起点并打印出该光标后的字符
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ch = fgetc(pf);
printf("%c\n", ch);//a
ch = fgetc(pf);
printf("%c\n", ch);//b
ch = fgetc(pf);
printf("%c\n", ch);//c
rewind(pf);
ch = fgetc(pf);
printf("%c\n", ch);//a
fclose(pf);
pf = NULL;
return 0;
}
1.文本文件读取失败时,一般返回EOF或NULL;二进制文件读取失败时,返回值小于实际要读的个数。但这些不能说明具体因为什么失败
2.一般读取失败的原因有两个,一是读取过程中遇到错误,用ferror函数检测;二是遇到文件末尾,用feof检测
(1)ferror函数
返回值:无错误时返回0;有错误时返回非零值
(2)feof函数
返回值:未到文件末尾返回0;到文件末尾返回非零值
通过两次判断,一次是ferror,一次是feof:
if (ferror(fp)):无错误返回0,有错误返回非零,进入if语句说明有错误。
else if (feof(fp)):未到末尾返回0,到末尾返回非零,进入if语句说明遇到文件末尾。
(1)文本文件的例子:
int main(void)
{
int c;
FILE* fp = fopen("test.txt", "r");
if (fp==NULL)
{
perror("File opening failed");
return 1;
}
//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
while ((c = fgetc(fp)) != EOF)
{
putchar(c);
}
//判断是什么原因结束的
if (ferror(fp))//无错误返回0,有错误返回非零
puts("I/O error when reading");//进入if语句说明有错误
else if (feof(fp))//未到末尾 返回0,到末尾返回非零
puts("End of file reached successfully");//进入if语句说明到末尾
fclose(fp);
fp = NULL;
}
(2)二进制文件的例子
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);
fp = NULL;
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 //读取的个数不等于实际个数,失败,判断失败原因
{
if (ferror(fp))//进入if语句说明遇到读取错误
{
perror("Error reading test.bin");
}
else if (feof(fp))//进入if语句说明遇到文件末尾
printf("Error reading test.bin: unexpected end of file\n");
}
fclose(fp);
fp = NULL;
}
“缓冲文件系统”是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。提高电脑工作效率。
正常情况是只有数据放满缓冲区后才能放入硬盘,但以下两种方法也可以将数据强制放入硬盘。
法1:刷新文件缓冲区:用fflush函数,参数为pf(流)
法2:关闭文件
例:证明不是因为fclose使数据存入文件(硬盘),而是fflush刷新使得数据从输入缓冲区到文件(硬盘)中:
#include
int main()
{
FILE* pf = fopen("data.txt", "w");
fputs("abcde", pf);
printf("睡眠10秒,已经写数据了,但打开文件后看不到内容\n");
Sleep(10000);
printf("刷新缓冲区\n");
fflush(pf);
printf("再睡眠10秒,打开文件后可以看到内容了\n");
Sleep(10000);
fclose(pf);
pf = NULL;
}
如果不关闭文件或刷新缓冲区,则放入缓冲区的数据可能会丢失。