C基础文件操作
Posted mChenys
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C基础文件操作相关的知识,希望对你有一定的参考价值。
目录
一、文件的打开和关闭
1.1 fopen函数
FILE *fopen(const char*path,const char*mode);
fopen打开文件成功则返回有效的FILE地址,失败则返回NULL
path就是指定打开文件的路径,可以是相对路径,也可以是绝对路径.
模式(mode)有以下几种:
- r:以只读的方式打开文件,该文件必须存在,且需要读的权限;
- rb:读写方式打开一个二进制文件,文件必须存在且需要读的权限,b选项在windows有效,windows所有文本都是\\r\\n结尾的,而不是\\n结尾的,如果读文件的时候没有带b,那么系统会自动把\\r吃掉;
- r+: 和r类似,只是它还可以写文件(前提是文件必须存在);
- w:打开只写文件,如果文件存在则文件长度清0,即该文件内容会消失,若文件不存在则建立文件,需要写的权限,在windows上会自动在\\n前补齐\\r;
- w+:和w类似, 只是它还可以读文件;
- wb:在Windows下有效,它可以避免系统自动在\\n前添加\\r字符;
- a:以追加的形式打开只写文件,若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留),需要写的权限;
- a+:和a类似,同时可以读和写
其中b选项是二进制的意思,可以和上面的所有模式组合使用。
注意:在windows上读写一个二级制文件,一般要加b,防止系统添加无畏的\\r;但如果读写的是一个文本文件,那么不要加b,这样可以不用单独处理这个\\r.
在Windows系统中,文本模式下,文件以"\\r\\n"代表换行,若以文本模式打开文件,并用fputs等函数写入换行符"\\n"时,函数会自动在"\\n"前面追加"\\r".即实际写入文件的是"\\r\\n".
在类unix/linux系统的文本模式下,文件是以"\\n"代表换行的,所以linux系统的文本模式和二进制模式没有区别.
1.2 fclose函数
关闭打开的文件 ,和fopen配套使用,只要fopen成功返回,那就需要调用fclose释放资源。
fclose(FILE *stream);
二、读取和写入字符
2.1 getc/fgetc函数
读取字符
int getc(FILE *stream);
getc的参数是一个fopen成功打开的文件后返回的指针,getc返回的是一个char, 它的功能是以字节位单位读取文件内容, 文本文件的最后结束标记是-1,也就是一个EOF宏定义 #define EOF -1
#include <stdio.h>
int main()
FILE *fp = fopen("user.txt", "r");
char c;
while ((c = getc(fp)) != EOF) //读取文件的每一个字符,直到末尾
printf("%c", c);
fclose(fp);
return 0;
2.2 putc/fputc函数
输出字符
int putc(int c,FILE *stream);
参数1是要写入的char,参数2是fopen返回的文件指针。
#include <stdio.h>
#include <string.h>
int main()
FILE *fp = fopen("a.txt", "w");
const char *s = "hello world";
int i;
for (i = 0; i < strlen(s); i++)
putc(s[i], fp); //向文件写入数据
putc('\\n', fp); //添加换行符
fclose(fp);
return 0;
C语言中fgetc、fputc和getc、putc的区别是什么?
千万不要认为fgetc、fputc的f代表的是file,就是这两个函数是和文件有关的!得看看他们的函数声明,如下图:
看到没,参数都是可以接收FILE指针的,其实那个f代表的其实是function。fgetc和getc他们的区别并不是在他们的使用上,而是在他们的实现上!具体来说,就是带f的(fgetc、fputc)实现的时候是通过函数来实现的,而不带f(putc、getc)的,实现的时候是通过宏定义来实现的!关于他们的不同点,就拿getc和fgetc来说:
- getc的参数不应当是具有副作用的表达式。
- 因为fgetc一定是一个函数,所以可以得到其地址。这就允许将fgetc的地址作为一个参数传送给另一个函数。
- 调用fgetc所需时间很可能长于调用getc,因为调用函数通常所需的时间长于调用宏。
2.3 案例-实现控制台输入文件名创建文件并支持写入功能
效果图如下:
打开目标文件
上代码:
#include <stdio.h>
int main(int argc, char **args)
if (argc < 2)
return 0;
FILE *fp = fopen(args[1], "w");
if (fp)
while (1)
printf("循环开始--\\n");
char c = getchar(); //从标准控制台中每次读取一个char,包括回车符
printf("收到%c\\n", c);
if (c == '0')
break;
putc(c, fp);
printf("--循环结束\\n");
fclose(fp);
return 0;
2.4 案例-实现控制台输入文件名读取该文件的内容
效果图如下:
#include <stdio.h>
int main(int argc, char **args)
if (argc < 2)
return 0;
FILE *fp = fopen(args[1], "r"); //根据用户输入的路径读取
if (fp)
char c;
while ((c = getc(fp)) != EOF)
printf("%c", c);
fclose(fp);
return 0;
2.5 案例-实现echo的功能
效果图:
查看a.txt文件内容如下:
#include<stdio.h>
#include<string.h>
int main(int argc,char **args)
if(argc <2)
return 0;
char *s = args[1]; //字符串内容
char *op = args[2]; // > or >> ,注意控制台输入需要转义, \\> 或者 \\>\\>
FILE *fp = NULL;
if(strcmp(">",op)==0)
fp = fopen(args[3],"w"); //新建
if(strcmp(">>",op)==0)
fp = fopen(args[3],"a"); //追加
if(fp)
int i;
for(i = 0;i<strlen(s);i++)
putc(s[i],fp);
putc('\\n',fp);//末尾添加换行
fclose(fp);
return 0;
或者
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **args)
if (argc != 4)
printf("Usage: test \\"hello\\" > a.txt");
return -1;
char *content = args[1];
char *op = args[2];
char *path = args[3];
FILE *f = NULL;
if (strcmp(op, ">") == 0)
f = fopen(path, "w");
else if (strcmp(op, ">>") == 0)
f = fopen(path, "a");
else
printf("Unknow option:%s\\n", op);
return -1;
if (f)
int size = strlen(content);
for (int i = 0; i <= size; i++) // 注意:这里包含了size,这样字符串末尾的'\\0'也能输出
putc(content[i], f);
//putc('\\n',f);//末尾添加换行
fclose(f);
return 0;
2.6 案例-实现文件拷贝的命令
#include<stdio.h>
int main(int argc, char **args)
if (argc != 3)
printf("Usage:test a.txt b.txt");
return -1;
FILE *src = fopen(args[1], "r");
FILE *dst = fopen(args[2], "w");
if (src && dst)
char c;
while ((c = getc(src)) != EOF)
putc(c, dst);
fclose(src);
fclose(dst);
return 0;
2.7 实现文件加解密
#include <stdio.h>
#include <string.h>
int main(int argc, char **args)
if (argc != 4)
printf("Usage: pwd a.txt b.txt 0\\n0:加密\\n1:解密\\n");
return -1;
FILE *src = fopen(args[1], "r");
FILE *dst = fopen(args[2], "a");
char *op = args[3]; // 这里也可以使用args[3][0]取字符来对比
if (src && dst)
char c;
while ((c = getc(src)) != EOF)
if (strcmp(op, "0") == 0)
// 加密
c++;
else if (strcmp(op, "1") == 0)
// 解密
c--;
putc(c, dst);
fclose(src);
fclose(dst);
return 0;
2.8 EOF与feof函数文件结尾
程序怎么才知道是否已经到达文件末尾了呢?EOF代表文件结尾,如果已经是文件的末尾,那么feof函数返回true,而EOF的值就是-1,在读文本文件的时候可以判断读到的字符是否是EOF或者调用feof返回true则表示读到文件的末尾了, 但是判断二进制文件则必须使用feof函数来判断. 因为字符的ASCII码不可能是EOF(-1), 但是二进制文件都是二进制数是可能出现-1的,所以二进制文件只能使用feof函数来判断。
int feof(FILE *stream);
feof函数的滞后性
feof函数每次都是判断FILE里面的一个标记,只有当执行fgets、getc、fread函数的时候才会更新FILE内的标记,所以feof函数有滞后性。也就是说在fgets、getc、fread函数前调用feof的结果是上一次的结果。
下面看一个错误的示例
#include <stdio.h>
int main()
FILE *fp = fopen("a.txt", "r");
if (fp)
char ch;
while (!feof(fp)) //feof函数需要在fgetc调用后才是最新的,所以当fgetc读到末尾的时候,此时feof判断还是上次的状态,也就是没有到末尾,这样就会多循环一次
ch = fgetc(fp);//当多循环一次的时候就会把EOF结束符也读取了.这样输出的结果就有问题了.
printf("%c", ch);
fclose(fp);
fp = NULL;
else
printf("打开文件失败");
return 0;
从输出结果可以看到多输出了一个字符.
正确的方式是这样的
#include <stdio.h>
int main()
FILE *fp = fopen("a.txt", "r");
if (fp)
char ch;
while (1)
ch = fgetc(fp);
if (feof(fp)) //改成在这里判断
break;
printf("%c", ch);
fclose(fp);
fp = NULL;
else
printf("打开文件失败");
return 0;
或者这样
#include <stdio.h>
int main()
FILE *fp = fopen("a.txt", "r");
if (fp)
char ch;
while ((ch = fgetc(fp)) != EOF)
printf("%c", ch);
fclose(fp);
fp = NULL;
else
printf("打开文件失败");
return 0;
三、读取和写入一行文本
3.1 fprintf和fscanf函数
这2函数都是通过FILE *来对文本文件(字符)进行行的读写(每次都是操作行数据),但不能用于操作二进制的文件(可执行程序,音乐等)。
int fscanf(FILE *stream, const char *format, ...); // 和sscanf功能一样,不同点是从文件中取解析
int fprintf(FILE *stream, const char *format, ...);// 和sprintf功能一样,不同点是向文件中输出
3.2 案例-将用户控制台输入的内容打印到文件中
#include<stdio.h>
#include<string.h>
int main()
FILE *wf = fopen("a.txt","w");
char buf[1024] = 0;
while(1)
scanf("%s",buf);
if(strcmp("exit",buf) ==0)
break;
fprintf(wf,"%s\\n",buf);//按指定格式输出到文件中
fclose(wf);
return 0;
3.3 fgets和fputs函数
这2个函数可以配套使用,一次读写一个字符串内容.
char *fgets(char *s, int size, FILE *stream); //每次读取一行字符串,包括换行符
int fputs(const char *s, FILE *stream); //每次输出一行字符串
下面实现从控制台输入内容到文件中保存
#include <stdio.h>
#include <string.h>
int main(int argc, char **args)
if (argc < 2)
return 0;
FILE *wf = fopen(args[1], "w");
while (1)
char buf[1024] = 0;
fgets(buf, sizeof(buf), stdin); //从控制台读取数据到buf中,注意fgets还可以从文件中读取,第三个参数改成FILE *即可
if (strncmp(buf, "exit", 4) == 0)
break;
fputs(buf, wf); //写到文件中
fclose(wf);
return 0;
3.4 案例-实现文件拷贝
#include<stdio.h>
int main(int argc,char **args)
C基础文件操作