函数库查找链接:C 标准库 – 参考手册 | 菜鸟教程
文件是硬盘储存数据内容必不可少的一部分,所以文件相关知识我们应当有所认知并熟练使用相关文件函数实现代码编译文件,读取文件。
例如 C:\code\test.txt
2.文件类型
文件分为程序文件(.c .obj .exe等等) 和 数据文件(txt)
后缀名称决定了其类型和默认打开方式
根据数据的组织形式,数据文件被称为文本文件或者二进制文件
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文
本文件。
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节(VS2013测试)。
简单来说二进制文件我们看不懂,文本文件我们看的懂
FILE*fopen(const char*filename,const char * mode)
int fclose (FILE * stream)
#include
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL) {
perror("test.txt");
}
fclose(pf);
return 0;
}
int fputc(int char, FILE *stream) 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。(所有输出流)
int fgetc(FILE *stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。读取失败了返回EOF(所有输入流)
#include
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL) {
perror("test.txt");
}
//输出一个字符到文件
fputc('a', pf);
//读取一个字符
int ch=fgetc(pf);
printf("%c\n", ch);
fclose(pf);
return 0;
}
int fputs(const char *str, FILE *stream) 把字符串写入到指定的流 stream 中,但不包括空字符。该函数返回一个非负值,如果发生错误则返回 EOF。
char *fgets(char *str, int n, FILE *stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
返回值:如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。如果发生错误,返回一个空指针。
#include
int main()
{
char str[20];
int i = 0;
FILE* pf = fopen("test.txt", "r");
if (pf == NULL) {
perror("test.txt");
}
//输出字符串到文件
fputs("hello world", pf);
//读取字符串到字符数组
fgets(str, 12, pf);
printf("%s\n", str);
fclose(pf);
return 0;
}
int fprintf(FILE *stream, const char *format, ...) 发送格式化输出到流 stream 中。如果成功,则返回写入的字符总数,否则返回一个负数。
int fscanf(FILE *stream, const char *format, ...) 从流 stream 读取格式化输入。如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。
#include
int main()
{
char str[20]="hello world!";
char tmp[20];
int i = 0;
FILE* pf = fopen("test.txt", "r");
if (pf == NULL) {
perror("test.txt");
}
//将str数组中字符串输出到pf所指向文件中
fprintf(pf, "%s", str);
//将pf文件中内容以格式化输出到数组tmp中
fscanf(pf, "%s", tmp);
//打印内容
printf("%s\n", tmp);
return 0;
}
简单来说就是输出输入流变成存字符串的数组
int sscanf(const char *str, const char *format, ...) 从字符串读取格式化输入。
int sprintf(char *str, const char *format, ...) 发送格式化输出到 str 所指向的字符串。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 从给定流 stream 读取数据到 ptr 所指向的数组中。
返回值:如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型。如果该数字与 nmemb 参数不同,则会显示一个错误。
- ptr -- 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
- size -- 这是要读取的每个元素的大小,以字节为单位。
- nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 把 ptr 所指向的数组中的数据写入到给定流 stream 中
返回值:成功读取的元素总数会以 size_t 对象返回,size_t 对象是一个整型数据类型。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。
#include
struct str
{
char name[10];
int age;
float score;
};
int main()
{
struct str buffer;
struct str str= { "张三",20,70.5f };
FILE* pf = fopen("test.txt", "rb");
if (pf == NULL) {
perror("test.txt");
}
//先输出到文件
fwrite(&str, sizeof(str), 1, pf);
//从文件中输入到结构体buffer中
fread(&buffer, sizeof(str), 1, pf);
//打印
printf("%s %d %4.2f",buffer.name,buffer.age,buffer.score);
return 0;
}
int fseek(FILE *stream, long int offset, int whence) 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。
void rewind(FILE *stream) 设置文件位置为给定流 stream 的文件的开头。
#include
int main ()
{
FILE *fp;
fp = fopen("file.txt","w+");
fputs("This is runoob.com", fp);
fseek( fp, 7, SEEK_SET );
fputs(" C Programming Langauge", fp);
fclose(fp);
return(0);
}
1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread判断返回值是否小于实际要读的个数。
这些函数前面详细写过,忘记可以翻看!
int feof(FILE *stream) 测试给定流 stream 的文件结束标识符。如果返回值为真,则说明读取到末尾结束,否则为读取错误导致结束读取
int ferror(FILE *stream) 测试给定流 stream 的错误标识符。如果设置了与流关联的错误标识符,该函数返回一个非零值,否则返回一个零值。
简单来说文件结束原因要不是错误,要不是已经完全读取到末尾,上面两个函数非此即彼。两个返回值一定有一个为真。
#include
#include
int main()
{
int c; // 注意:int,非char,要求处理EOF
FILE* fp = fopen("test.txt", "r");
if(!fp) {
perror("File opening failed");
return EXIT_FAILURE;
}
//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回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);
return 0;
}
ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
#include
//VS2013 WIN10环境测试
int main()
{
FILE*pf = fopen("test.txt", "w");
fputs("abcdef", pf);//先将代码放在输出缓冲区
printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
Sleep(10000);
printf("刷新缓冲区\n");
// int fflush(FILE *stream) 刷新流 stream 的输出缓冲区
fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
//注:fflush 在高版本的VS上不能使用了
printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
Sleep(10000);
fclose(pf);
//注:fclose在关闭文件的时候,也会刷新缓冲区
pf = NULL;
return 0;
}
文件这一节内容上并不难,但是有很多函数需要我们熟练它们,愿大家能静下心来自己写一写这些函数用法,以后遇到游刃有余!