萌新的学习笔记,写错了恳请斧正。
目录
文件的随机读写是指我们可以控制文件位置指示器(光标)的位置,以完成复杂的读写操作
#include <stdio.h>
int fseek( FILE* stream, long offset, int origin );
fseek函数用于移动文件位置指示器(光标)的位置,移动成功则返回0,发生错误则光标位置不变、返回非0整数并设置流结构体上的错误指示器。
其中,origin是基准位置,可以取值有:SEEK_SET(文件头)、SEEK_CUR(当前光标位置)、SEEK_END(文件尾),一般这三个值分别是0、1、2(最好不要这样写)。而offset为偏移的字节数,代表以origin为基准偏移特定字符,比方说origin为SEEK_CUR且offset为-1时,就将光标左移一个字节。
文件被写入“This is a sample.”
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* pf = fopen("file.txt", "w");
if (pf == NULL)
{
perror("fopen");
return EXIT_FAILURE;
}
fputs("This is an apple.", pf);
fseek(pf, 9, SEEK_SET);
fputs(" sam", pf);
fclose(pf);
pf = NULL;
return EXIT_SUCCESS;
}
#include <stdio.h>
long ftell( FILE* stream );
ftell用于返回此时文件位置指示器相对文件头的偏移量
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* pf = fopen("file.txt", "w");
if (!pf)
{
perror("fopen");
return EXIT_FAILURE;
}
fputs("1145141919810", pf);
printf("%d\n", ftell(pf));
fseek(pf, 0, SEEK_SET);
printf("%d\n", ftell(pf));
fseek(pf, 7, SEEK_CUR);
printf("%d\n", ftell(pf));
return EXIT_SUCCESS;
}
#include <stdio.h>
void rewind( FILE* stream );
rewind函数用于将文件位置指示器返回到文件起始位置
效果等于offset为0且origin为SEEK_SET的fseek函数
#include <stdio.h>
int feof( FILE *stream );
feof检查流结构体上的文件尾指示器,如果指示器被设置则返回非0值,否则返回0
feof函数的作用是:当文件读取结束,判断结束的原因是否是“遇到文件尾”
请不要在读取过程中使用feof的返回值来判断文件是否读到结束
#include <stdio.h>
int ferror( FILE* stream );
ferror检查流结构体上的错误指示器,如果指示器被设置则返回非0值,否则返回0
先判断读取是否结束,如果读取结束则通过feof和ferror判断是遇到文件尾结束还是出错
比方说我们处理文本文件可以:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* fp = fopen("test.txt", "r");
if (!fp)
{
perror("File opening failed");
return EXIT_FAILURE;
}
int c; // 注意:int,非char,要求处理EOF
while ((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);
fp = NULL;
return EXIT_SUCCESS;
}
处理二进制文件可以:
#include <stdio.h>
#include <stdlib.h>
enum { SIZE = 5 };
double a[SIZE] = { 1.,2.,3.,4.,5. };
double b[SIZE];
int main()
{
FILE* fp = fopen("test.bin", "wb"); // 必须用二进制模式
if (!fp)
{
perror("fopen-wb");
return EXIT_FAILURE;
}
fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组
fclose(fp);
fp = fopen("test.bin", "rb");
if (!fp)
{
perror("fopen-rb");
return EXIT_FAILURE;
}
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 (feof(fp))
printf("Error reading test.bin: unexpected end of file\n");
else if (ferror(fp))
perror("Error reading test.bin");
} // error handling
fclose(fp);
fp = NULL;
return EXIT_SUCCESS;
}
ANSIC标准采用“文件缓冲系统”来处理数据文件。
也就是说,系统会在内存中为每个打开的文件流创建一个“文件缓冲区”。内存中运行的程序如果想对外存中的文件进行I/O(输入输出)操作,传递的信息就需要通过输入缓冲区和输出缓冲区。
在不刷新缓冲区的情况下,信息只有在填满整个输入/输出缓冲区后,整个缓冲区的信息才会整个打包发送给程序/文件,否则信息将滞留在缓冲区直到被刷新。
刷新缓冲区是指将已经写到输入缓冲区的信息冲入、已经写到输出缓冲区的信息冲出;将尚未写入缓冲区的信息舍弃
由于缓冲区的存在,我们在更新模式(存在标签"+")下打开文件时:
- 若中间没有fflush函数或文件定位函数,则输出后不应有输入
- 若中间没有文件定位函数且输入操作没有遇到文件尾,则输入后不应有输出
#include <stdio.h>
int fflush( FILE* stream );
fflush函数用于刷新缓冲区,成功返回0,否则返回EOF并设置流结构体的错误指示器
如果输入空指针,则刷新所有缓冲区