本文通过串联c语言的常规输入输出包括的基本函数以及使用进行总结并且详解,如有问题希望大家积极指出并且改正,下面将本文内容和大家分享。
c语言中的文件包括块设备文件(-b),字符设备文件(-c),目录文件(-d),普通文件(-f),等等。普通文件可以进行标准IO和文件IO,那么本文也将从最常使用的标准IO作为切入来以标准、文件、目录IO的讲解顺序为大家讲解。
编辑角度:
1.库函数-------------------------标准IO
2.系统调用----------------------文件IO(Linux内核提供函数接口)
3.对于目录的操作-------------目录IO
【操作文件的基本思路及框架】//凡是文件,都可从这个思路出发进行思考
文件操作三步骤:
1.打开
2.读写
3.关闭
一、标准IO(各个接口函数)
1.打开文件
函数接口:fopen
FILE *fopen(const char *path,const char *mode)
作用:
- 打开文件,并关联到一个流。
参数:
- path ----要打开的文件的文件名(字符串形式)
- mode --打开文件的操作模式
操作指令 | 指令作用 | 注意事项 |
r | 打开文件做读操作 | 文件必须存在 |
r+ | 打开文件做读写操作 | 文件必须存在 |
w | 打开文件做写操作 | 如果文件已经存在,则会将文件清空为0, 如果文件不存在,则会创建一个新文件 |
w+ | 打开文件做读写操作 | 如果文件已经存在,则会将文件清空为0,如果文件不存在,则会创建一个新文件。 |
a | 打开文件做写操作 | 如果文件已经存在,则在文件末尾进行写入,如果文件不存在,则会创建一个新文件。 |
a+ | 打开文件做读写操作 | 如果文件已经存在,则在文件末尾进行写入,如果文件不存在,则会创建一个新文件。 |
返回值:
- 成功 FILE * (文件流指针)
- 失败 NULL 并且 设置 errno 表明错误原因。
FILE *fp = fopen("1.txt", "w"); if(fp == NULL) { printf("Fail to fopen.\n"); return -1; }
- 以上代码段为以w命令的模式打开(或创建)了1.txt文件。
- fp则为文件流指针
- 命令方式r、w、a决定了后续对该文件操作的权限
2.关闭文件
函数接口:fclose
int fclose(FILE *stream);
作用:
- 关闭文件
参数:
- stream则为文件流指针(上述打开文件中的fp)
返回值:
- 成功返回0
- 失败返回EOF(-1)
代码演示
fclose(fp);
- 以上代码为关闭指针流fp(清除指针fp使它不指向规定的文件)
- 如果创建文件流指针后记得关闭文件流指针不然会导致空间泄露。
3.写文件
该模块分为两个函数接口fputc,fputs以及fwrite(最左边两个函数仅有写入长度区别,而fwrite即可以操作二进制文件也可以操作ASCII文件),我逐一为大家介绍。
函数接口:fputc
int fputc (int c, FILE *stream);
作用:
- 向文件中写入一个字符
参数:
- c:要写入的字符
- stream:文件流指针
返回值:
- 成功返回 写入的字符ASCII码值
- 失败返回 EOF
代码演示
char s[20] = {"Hello World"}; int i; for(i = 0;i < strlen(s);++i) { int ret = fputc(s[i], fp); if(EOF == ret) { printf("Fail to fputc\n"); } }
以上代码为向文件中写入Hello World,由于fputc只能一个一个字符的写入所以如果想写入一串字符则需要应用循环。
函数接口:fputs
int fputs(const char *s,FILE *stream);
作用:
- 通过文件流指针向文件中写入一行字符串
参数:
- s为要写的信息,一般是固定的字符串或者有数据的数组。
- stream 要写入的目标文件流对象
返回值:
- 成功 返回非负数
- 失败 -1
代码示例
char s[] = {"Hello World"}; int ret = fputs(s, fp); if(EOF == ret) { printf("fail to fputs.\n"); }
- 以上代码和上述的fputc一样都向fp指向的文件中输入了hello world字符,但是fputs就不需要循环因为输入的是一行字符
- 注意fputs不输入'\0',fputs不会自动增减'\n'这一点与puts也有一定的不同需要注意!!
- 正是由于fputs不输入'\0'的原因才导致fputs不能进行二进制文件的操作,因为二进制文件内有大量的'\0'但是不能读入
函数接口:fwrite
size_t fwrite(const void *ptr, size_t, size, size_t nmemb, FILE *stream)
作用:
- 从ptr所在本地内存中取出nmemb个大小为size的数据块写入到stream流对应的文件流对象中。
参数:
- ptr 要写的数据块地址,一般是数组或者结构体指针
- size 要写的数据块元数据大小,单位是字节
- nmemb 要写的数据块的个数
- stream 要写的目标文件流对象。如果是stdout则表示数据会写到终端屏幕显示,如果是fp的普通文件则会写入到文件中。
返回值:
- 成功 小于等于nmemb 的个数。
- 失败 <0
代码示例
struct stu { char name[32]; int id; int score; }; struct stu s[3] = {{"Zhangsan", 1, 82}, {"Lisi", 2, 70}, {"Wanger", 3, 90}}; size_t a = fwrite(s, sizeof(struct stu), 3, fp);//用a来接收fwrite的返回值来判断
以上代码来展示fwrite的作用,各个参数的数值以及作用,fwrite多用于二进制文件操作
4.读文件
该模块是通过文件留指针在文件中提取出想要的内容,写文件一样也有对应的三个函数接口fgetc,fgets,fread,下面让我为大家详细的介绍一下
函数接口:fgetc
FILE *stream
作用:
- 从文件中读取一个字符
参数:
- stream:文件流指针
返回值:
- 成功返回读到字符的ASCII码值
- 读到文件末尾 返回 EOF
- 失败返回EOF (-1)
代码示例
int ch = fgetc(fp); if(EOF == ch) { printf("fail not to fgetc or end"); } printf("%c\n", ch);
以上代码的含义为从fp指向的文件中从头开始提取一个字符并且判断是否读到文件结尾或者失败。
函数接口:fgets
char *fgets(char *s, int size, FILE *stream);
作用:
- 从文件流指针指向的文件中获取size大小字节的文本数据并存储到s对应的本地内存(栈区数组,堆区内存)
参数:
- s为要存储数据的本地内存的地址(栈,堆)
- size 要获取的数据长度,单位字节
- stream 要获取的目标文件流对象。
返回值:
- 成功 返回指向有效数据的首地址,一般等于s的地址
- 失败 或者 文件末尾 NULL;
代码示例
while(1) { char buff[1024] = {0}; char *p = fgets(buff, sizeof(buff), fp1); if(NULL == p) { printf("Fail to fgets or end.\n"); break; } int ret = fputs(p, fp2); if(EOF == ret) { printf("Fail to fputs.\n"); break; } }
以上代码的含义是将fp1指向的文件的内容提取出来并且传递到fp2指向的文件来保存。
PS:
- 能读取一行就读取一行(读不完读规定的size-1)
- fgets会读到n个数据,如果n个数据中存在\n字符则立即停止(换行符为结束的标志)
- fgets每行读取的数据后面都有一个\n,在\n后面存放一个\0变成一个字符串
- gets是危险的,因为没有规范读到数据的上限
- 区别fgets与gets fgets输入啥输出啥包括换行符 gets会自动省略换行符\n
函数接口:fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
作用:
- 从文件留指针指向的文件中获取nmemeb个大小为size字节的数据块到ptr所在的本地内存中。
参数:
- ptr 要写的数据块地址,一般是数组或者结构体指针
- size 要写的数据块元数据大小,单位是字节
- nmemb 要写的数据块的个数
- stream 要写的目标文件流对象(如果是stdout则表示数据会写到终端屏幕显示,如果是fp的普通文件则会写入到文件中)
返回值:
- 成功 小于等于nmemb 的个数。
- 失败 <0
代码示例
{ char name[32]; int id; int score; }; struct stu s[3]; memset(s, 0, sizeof(s)); size_t ret = fread(s, sizeof(struct stu), 3, fp1); printf("%lu\n", ret);
以上代码为从fp1指向的文件中读取内容放到结构体数组s中并且输出fread的返回值来判断是否函数调用成功。
总结普通文件常用fgets/fputs来操作,二进制文件常用fread/fwrite来操作,fgetc/fputc可以用于两种文件均可但是一次只能操作一个字符,相对来说有些过于麻烦需要添加循环,在短小的文件内容操作中可以利用以上一组函数,而fopen/fclose为一组开关函数接口,记得文件流指针打开有借有还,在函数的收尾要记得关闭文件流指针,养成好习惯。
本文详细的讲解了标准IO的各个函数接口供大家学习,在后续的文章中将为大家介绍后续的文件IO以及目录IO等常用的IO接口函数供大家交流学习,如果有问题或者意见希望大家在评论区内指出,答主一直在线与大家共同讨论!