文件操作的函数在标准库stdio.h中。
#include <>
1、fopen, fclose 打开文件,关闭文件
fopen:打开文件。
fclose:关闭文件。
补充:perror:输出errno对应的错误信息。
fopen: FILE *fopen(const char *filename, const char *mode)
参数:filename是字符串(要打开的文件),mode是访问模式。
返回:FILE指针,指向打开的文件。若文件不存在,返回NULL。
注意:
使用fopen打开文件,使用完文件立即用fclose关闭文件。否则会资源泄露、数据丢失、影响其它进程。
打开文件后,FILE指针指向文件在内存的位置。文件内部有位置指针(位置标识符),在指针所在位置读取/写入内容。
fclose: int fclose(FILE *fp)
参数:fp是已打开的文件。
返回:若成功关闭,返回0。若关闭失败,返回EOF。
EOF是在标准库中的宏定义,表示已经到达文件末尾,是个负整数常量。
文件 | 模式 | 描述 |
---|---|---|
文本文件 | r | 打开一个已有的文本文件,只能读取。 |
文本文件 | w | 打开一个文本文件,只能从头写入内容。如果文件不存在,则会创建一个新文件。 从文件的开头重新写入内容。相当于每次打开文件都是一个空文件。 |
文本文件 | a | 打开一个文本文件,只能追加写入内容。如果文件不存在,则会创建一个新文件。 在已有的文件内容中追加内容。 |
文本文件 | r+ | 打开一个已有的文本文件,允许读和写。 |
文本文件 | w+ | 打开一个文本文件,允许读和写。如果文件不存在,则会创建一个新文件。 从文件的开头重新写入内容。相当于每次打开文件都是一个空文件。 |
文本文件 | a+ | 打开一个文本文件,允许读取和追加写入。如果文件不存在,则会创建一个新文件。 读取会从文件的开头开始,写入则只能是追加模式。 |
二进制文件 | rb | 打开一个已有的二进制文件,只能读取。 |
二进制文件 | wb | 打开一个二进制文件,只能从头写入内容。如果文件不存在,则会创建一个新文件。 从文件的开头重新写入内容。相当于每次打开文件都是一个空文件。 |
二进制文件 | ab | 打开一个二进制文件,只能追加写入内容。如果文件不存在,则会创建一个新文件。 在已有的文件内容中追加内容。 |
二进制文件 | rb+ | 打开一个已有的二进制文件,允许读和写。 |
二进制文件 | wb+ | 打开一个二进制文件,允许读和写。如果文件不存在,则会创建一个新文件。 从文件的开头重新写入内容。相当于每次打开文件都是一个空文件。 |
二进制文件 | ab+ | 打开一个二进制文件,允许读取和追加写入内容。如果文件不存在,则会创建一个新文件。 读取会从文件的开头开始,写入则只能是追加模式。 |
#include <>
int main(void)
{
FILE *file;
file = fopen("","r"); // 打开文件,(文件不存在)
printf("file is %s\n", file); // 若打开的文件不存在,fopen返回NULL
// 文件具体操作,此处省略
fclose(file); // 关闭文件
return 0;
}
// 结果:
file is (null)
打开文件时,若发生错误(例如:只读模式下文件不存在),会用标准库errno.h中的全局整数变量errno来记录错误号。
通过标准库string.h中的strerror 获取errno对应的错误信息。
通过标准库stdio.h中的perror 输出errno对应的错误信息。
perror: void perror(const char *str)
参数:字符串(自定义信息,在系统错误信息之前显示)
返回:无。
注意:perror 输出错误信息。 将errno对应的错误信息输出到标准错误(stderr)。
#include <>
#include <>
#include <>
int main(void)
{
FILE *file;
file = fopen("","r"); // 打开文件
printf("%s\n",strerror(errno)); // 若打开的文件不存在,全局变量errno会记录错误号,strerror获取对应错误信息
if(file == NULL)
{
perror("Open file failed"); // perror输出错误信息,将errno对应的错误信息输出到标准输出(stderr)
return -1;
}
fclose(file); // 关闭文件
return 0;
}
// 结果:
No such file or directory
Open file failed: No such file or directory
2、fputc, fputs, fwrite, fprintf 往文件中写入内容
fputc:将一个字符写入文件。
fputs:将字符串写入文件(不包括结束符'\0')。
fwrite:将数组中的数据写入文件
fprintf:将格式化字符串写入文件。
fputc: int fputc(int char, FILE *stream)
参数:char是要写入的一个字符(转为对应的int值来传递),stream是被写入的文件。
返回:被写入的字符。若发生错误,返回EOF,并设置错误标识符。
#include <>
int main(void)
{
FILE *file;
file = fopen("", "w"); // 打开文件,"w"只能写。若追加内容,访问模式用"a"
// 写入26个大写字母
for(int c = 65; c < 65+26; c++)
{
fputc(c, file); // 写入一个字符
}
fclose(file);
return 0;
}
// 结果:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
fputs: int fputs(const char *str, FILE *stream)
参数:str是要写入的字符串,stream是被写入的文件。
返回:非负值。若发生错误,返回EOF。
注意:字符串是以结束符'\0'为终止的字符数组,但结束符'\0'不会被写入文件中。
结束符'\0':NUL,空字符,表示字符串的结束。
#include <>
int main(void)
{
FILE *file;
file = fopen("", "w");
fputs("hello world, good luck", file); // 写入字符串
fclose(file);
return 0;
}
// 结果:
hello world, good luck
fwrite: size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
参数:ptr是要写入的数组(指向数组的指针),size是数组中每个元素的内存大小,nmemb是要写入的元素个数,stream是被写入的文件。
返回:被写入的元素总数。
#include <>
int main(void)
{
FILE *file;
file = fopen("","w");
char s[] = "Have a good day, good luck.";
// 将数组的数据写入文件
fwrite(s, sizeof(char), 16, file); // 写入数组中16个字符
fputc('\n', file); // 写入一个字符:换行符
fwrite(s, sizeof(char), sizeof(s), file); // 写入数组中所有字符(包括结束符'\0'即NUL即空字符)
fclose(file);
return 0;
}
// 结果:
Have a good day,
Have a good day, good luck.
fprintf: int fprintf(FILE *stream, const char *format,...)
参数:stream是被写入的文件。format是要写入的字符串(包括格式化说明符)。
返回:被写入的字符总数。若写入失败,返回负数。
#include <>
int main(void)
{
FILE *file;
file = fopen("","w");
fprintf(file, "%s %s\n", "123", "234"); // 格式化输出到文件中
fprintf(file, "%s %s %s\n", "hello", "good", "luck");
fclose(file);
return 0;
}
// 结果:
123 234
hello good luck
3、fgetc, fgets, fread, fscanf 读取文件内容
fgetc: 从文件中读取一个字符。
fgets:从文件中读取一行(指定读取最大字符数)。
fread:从文件中读取数组中的数据。
fscanf:从文件中读取格式化输入。
补充:feof:判断是否到达文件末尾。
ferror:判断是否有错误信息码。
clearerr:清除文件结束和错误信息码。
fgetc: int fgetc(FILE *stream)
参数:被读取的文件。
返回:读取的字符。若到达文件末尾或发生错误,返回EOF。
补充:feof 判断是否到达文件末尾
feof: int feof(FILE *stream)
参数:stream是要操作的文件。
返回:没有到达文件末尾,返回0。到达文件末尾(碰到文件结束标识符),返回非零值。
#include <>
int main(void)
{
FILE *file;
char c;
file = fopen("", "r"); // 打开文件。内容:Have a good day, good luck!
while(1)
{
c = fgetc(file); // 读取一个字符
if(feof(file)) // 到达文件末尾(即feof返回非零值),退出while循环
{
break;
}
printf("%c",c);
}
fclose(file); // 关闭文件
return 0;
}
// 结果:
Have a good day, good luck!
若读取时发生错误,可用ferror捕捉错误标识符。用clearerr清除文件结束和错误标识符。
ferror: int ferror(FILE *stream)
参数:stream是要操作的文件。
返回:若设置了错误标识符,返回非零值。若没有错误标识符,返回0。
clearerr: void clearerr(FILE *stream)
参数:stream是要操作的文件。
返回:无。若参数是无效的stream,则返回-1,并设置errno为EBADF("Bad file descriptor",表示文件描述符无效或不合法)。
#include <>
int main(void)
{
FILE *file;
char c;
file = fopen("", "w"); // 打开文件。"w"只能写,不能读取
while(1)
{
c = fgetc(file); // 读取一个字符,若发生错误,会设置错误标识符
if(ferror(file)) // 判断是否有错误标识符,若非零值则有错误
{
printf("Read file failed");
break;
}
printf("%c",c);
}
clearerr(file); // 清除文件结束和错误标识符
fclose(file);
return 0;
}
// 结果:
Read file failed
fgets: char *fgets(char *str, int n, FILE *stream)
参数:str是存储要读取的字符串(指向字符数组的指针),n是读取的字符数(包括空字符),stream是被读取的文件。
返回:相同的str参数(str指向字符数组的指针)。若到达文件末尾或发生错误,返回空指针。
注意:fgets 指定读取最大字符数(包括最后的空字符),若读取到n-1个字符或碰到换行符或到达文件末尾就会停止读取。
#include <>
int main(void)
{
FILE *file;
char s[16];
file = fopen("", "r"); // 打开文件。内容:Have a good day, good luck!
if(fgets(s, 16, file) != NULL) // 读取16个字符的字符串(读取15个字符,1个空字符结束字符串)
{
printf("%s", s);
}
fclose(file);
return 0;
}
// 结果:
Have a good day
fread: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
参数:ptr是存储读取内容的数组(最小内存大小size*nmemb),size是数组中每个元素的内存大小,nmemb是要读取的元素个数,stream是被读取的文件。
返回:成功读取的元素总数。若元素总数与参数nmemb设置的数不同,则可能发生错误或到达文件末尾。
#include <>
int main(void)
{
FILE *file;
char s[16];
file = fopen("", "r"); // 打开文件。内容:Have a good day, good luck!
fread(s, sizeof(char), 15, file); // 读取数组中的15个字符
printf("%s", s);
fclose(file); // 关闭文件
return 0;
}
// 结果:
Have a good day
fscanf: int fscanf(FILE *stream, const char *format,...)
参数:stream是被读取的文件,format是字符串(包括格式化说明符)。
返回:成功匹配和赋值的字符个数。若到达文件末尾或发生错误,返回EOF。
#include <>
int main(void)
{
FILE *file;
char s1[8], s2[8], s3[8];
int k;
file = fopen("", "r"); // 打开文件。内容:This year is 2024, good luck!
fscanf(file, "%s %s %s %d", s1, s2, s3, &k); // 读取格式化输入(碰到空格就读取结束,读取下一个格式化字符串)
printf("%s\n%s\n%s\n%d", s1, s2, s3, k);
fclose(file);
return 0;
}
// 结果:
This
year
is
2024
4、文件内部指针(位置标识符)的当前位置
ftell:获取文件内部指针的当前位置。
rewind:设置文件内部指针的当前位置为文件开头。
fseek:设置文件内部指针的当前位置(开头SEEK_SET,当前位置SEEK_CUR,末尾SEEK_END)。
fgetpos:.获取文件内部指针的当前位置,并写入pos。
fsetpos:设置文件内部指针的位置为给定位置(fgetpos获取的pos值)。
ftell: long int ftell(FILE *stream)
参数:stream是要操作的文件。
返回:文件内部指针的当前值。若发生错误,返回-1L,并设置全局变量errno为正值。
rewind: void rewind(FILE *stream)
参数:stream是要操作的文件。
返回:无。
fseek: int fseek(FILE *stream, long int offset, int whence)
参数:stream是要操作的文件,offset是相对于参数whence的偏移量,whence是文件内部指针开始偏移的位置(开头SEEK_SET,当前位置SEEK_CUR,末尾SEEK_END)。
返回:0。若发生错误,返回非零值。
fgetpos: int fgetpos(FILE *stream, fpos_t *pos)
参数:stream是要操作的文件,pos是指向fpos_t对象的指针(fpos_t对象记录文件内部指针当前位置)。
返回:0。若发生错误,返回非零值。
注意:pos指向的对象,其值以内部格式存储,仅供fgetpos和fsetpos使用。
fsetpos: int fsetpos(FILE *stream, const fpos_t *pos)
参数:stream是要操作的文件,pos是通过fgetpos获得的位置(指向fpos_t对象的指针)。
返回:0。若发生错误,返回非零值,并设置全局变量errno为正值。
#include <>
#include <>
int main(void)
{
FILE *file;
fpos_t position;
// "wb"二进制只写模式(写完关闭文件,再次以可读的方式打开文件才能读取。"wb+"模式可边写边读)
file = fopen("", "wb");
// 若打开文件失败,输出错误信息,并退出程序
if(file == NULL)
{
perror("Open file failed");
return -1;
}
// 往空文件写入内容
char s1[] = "have a good day ";
fwrite(s1, sizeof(char), strlen(s1), file);
fgetpos(file, &position); // fgetpos:获取文件内部指针的当前位置,并写入position
// 继续写入内容
char s2[] = "good luck ";
fprintf(file, "%s", s2);
fsetpos(file, &position); // fsetpos:设置文件内部指针的当前位置为 fgetpos获取的位置
// 通过fsetpos回到fgetpos获取的位置,写入内容,覆盖原来的内容
char s3[] = "learn C programming language";
fputs(s3, file);
rewind(file); // rewind:设置文件内部指针的当前位置为文件开头
// 回到开头,写入内容,覆盖原来的内容
char s4[] = "hello world";
for(int i = 0; i < strlen(s4); i++)
{
fputc(s4[i], file);
}
fseek(file, 0, SEEK_END); // fseek:设置文件内部指针的当前位置,此处设为文件末尾
int length;
length = ftell(file); // ftell:获取文件内部指针的当前位置
printf("file has %d char\n", length);
// 关闭文件
fclose(file);
// 打开文件,只读
file = fopen("", "r");
int c;
while(1) // 读取文件所有内容
{
c = fgetc(file); // 一个字符一个字符读取
if( feof(file) ) // 若到达文件末尾,就退出while循环
{
break;
}
printf("%c",c);
}
// 关闭文件
fclose(file);
return 0;
}
// 结果:
file has 44 char
hello world day learn C programming language