C语言笔记:C的文件操作
-
- C语言的文件操作的理论
- 函数1 FILE * fopen(const char * url,const char* mode)
- 函数2 int fclose(FILE *stream)
- 函数3 int fgetc(FILE *stream)
- 函数4 int fputc(FILE *stream)
- 函数5 char *fgets(char *str, int n, FILE *stream)
- 函数6 int fputs(const char *str, FILE *stream)
- 函数7 int fprintf(FILE *stream, const char *format, ...)
- 函数8 int fscanf(FILE *stream, const char *format, ...)
- 函数9 size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
- 函数10 size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
- 其他函数
C语言的文件操作的理论
- 数据流
- 缓冲区buffer
stdio.h头文件里的文件操作是带缓冲区的,也就是在内存里开辟出一块空间,程序的各个操作是先和内存进行交互,在交互完成、缓冲区满了、flush或close后,才会从缓冲区导入到磁盘中,因为内存的读取速度是远远大于磁盘的。
函数1 FILE * fopen(const char * url,const char* mode)
- 说明:fopen函数用于打开文件流
- 参数:
- 字符串类型–>文件的路径
文件的路径记得要加入转义字符。 - 字符串类型–>对这个文件的处理方式
处理方式有:
r–>只读,且文件必须存在
w–>创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容, 文件被视为一个新的空文件。
a 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。
r+ 打开一个用于更新的文件,可读取也可写入。该文件必须存在。
w+创建一个用于读写的空文件。
a+ 打开一个用于读取和追加的文件。
- 字符串类型–>文件的路径
- 返回值:
- 文件存在,返回文件指针FILE
- 文件不存在,返回NULL
FILE *fp;
//注意路径里的转义字符
fp = fopen("C:\\Users\\41061\\Desktop\\cfile.txt","r+");
if(fp == NULL){
printf("文件不存在");
return 0;
}else{
printf("已经打开了文件\n");
}
函数2 int fclose(FILE *stream)
- 说明:fclose用于关闭文件流
- 参数:
- FILE指针–>需要关闭的文件流
- 返回值:
- 流成功关闭,则该方法返回零
- 失败,则返回 EOF。
函数3 int fgetc(FILE *stream)
- 说明: fgetc 获取流中光标当前位置后的一个字符,他的返回值是int类型,读取到的字符char会强转为int。
- 参数:
- FILE指针–>要读取的流
- 返回值:
- 读取成功 返回字符(int类型)
- 到达文件末尾或发生读错误,返回 EOF
/*这里成功读取了字符 注意fgetc的返回值是int*/
int c;
//判断是否到了文件尾
while( (c = fgetc(fp)) != EOF ){
printf("%c",c);
}
printf("\n文件内容输出完毕\n");
函数4 int fputc(FILE *stream)
- 说明:fputc 向流里写入一个字符,具体写在哪里,是开头 ,还是光标的位置,还是追加,seek里另说。这里在测试的时候出现了一个问题,文件里有若干个字符,我用fgetc读取一个后,再使用fputc追加模式,就无法追加了。
- 参数:
- FILE指针–>要读取的流
- 返回值:
- 写入成功 返回写入的字符(int类型)
- 发生错误,返回 EOF
int c;
while( (c = getchar()) != '\n'){
fputc(c,fp);
printf("写入了%c\n",c);
}
printf("\n文件写入完毕");
//这种情况下使用a+模式 ,无法追加。
printf("%c",fgetc(fp));
/*fputc是写入字符*/
int c;
while( (c = getchar()) != '\n'){
fputc(c,fp);
printf("写入了%c\n",c);
}
printf("\n文件写入完毕");
函数5 char *fgets(char *str, int n, FILE *stream)
- 说明:函数的作用是在流中读取,返回一个字符串指针。
- 参数:
- 字符串指针–>指向读取好的字符串
- 整型–>指定读取的长度 比如5,实际上读取4个,最后一个是空。 “ABCDE” 读取5个,返回的是ABCD 。
- FILE文件流
- 返回值:它的返回值和第一个参数是一样的。如果读取失败会返回空指针。
//这里一定要初始化一下,不能仅仅定义一个指针,就算要定义指针,也要为指针初始化。
char str[1024];
fgets(str,1024,fp);
printf("使用fgets读取到的字符串:%s",str);
函数6 int fputs(const char *str, FILE *stream)
- 说明:函数的作用是往流中输入一串字符串。
- 参数:
- 字符串–>输入的字符串
- 文件流
- 返回值: 它的返回值是一个int类型,该函数返回一个非负值,如果发生错误则返回 EOF。
char str[1024];
//stdin是键盘的标准输入
if(fputs(fgets(str,5,stdin),fp) != EOF)
printf("输入成功%s",str);
else
printf("输入失败");
函数7 int fprintf(FILE *stream, const char *format, …)
- 说明:printf是把内容输出到终端显示器上,就会显示出来,而fprintf是输出到文件里,在文件中显示。print原意为打印,输出。所谓输入输出,都是相对于程序而且,从程序到文件,就是输出。
- 参数:参数很多,总的分为3块。
- 流
- 格式 %d %c %s这些
- 内容 就是格式里的%d %c %s 的内容
- 返回值:如果成功,则返回写入的字符总数,否则返回一个负数。
char str1[] = "hello";
char str2[] = "world";
int num = fprintf(fp,"%s %s",str1,str2);
//返回值是11 因为有一个空格
printf("%d",num);
函数8 int fscanf(FILE *stream, const char *format, …)
-
说明:这是标准输入函数,以前scanf是从键盘输入到程序,现在是从文件输入到程序。
-
参数:
- 流
- 格式 %d %c %s这些
- 指针 存放读取到的字符。
-
返回值:如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。
hello world ABCD
char str1[10],str2[10],*c1,*c2,*c3,*c4;
fscanf(fp,"%s %s %c %c %c %c",str1,str2,&c1,&c2,&c3,&c4);
printf("%s %s %c %c %c %c",str1,str2,c1,c2,c3,c4);
已经打开了文件
hello world A B C D
--------------------------------
Process exited after 0.03082 seconds with return value 0
请按任意键继续. . .
函数9 size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
-
说明:从文件里,以二进制形式,读取文件。读取count个项,每个项的大小是size。
-
参数:
- ptr 读取到的数据,存放的地址。
- size 一次读取的数据大小
- count 这是读取的个数,每个元素的大小为 size 字节。
- stream 文件流
-
返回值:成功读取返回是一个整型数据类型。
函数10 size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
-
说明:向文件里,以二进制形式,输出数据。读取count个项,每个项的大小是size。
-
参数:
- ptr 输出的数据指针。
- size 一次输出的数据大小
- count 输出的个数,每个元素的大小为 size 字节。
- stream 文件流
-
返回值:成功返回是一个整型数据类型。
//这样就是输出成功了,写入到了文件
char str[] = "ABCD";
fwrite(str,sizeof(char),3,fp);
下面是关于结构体的
typedef struct Stu{
char *name;
int age;
};
1.一个结构体,写入到文件里,然后格式化输出
Stu s;
s.name = "tom";
s.age = 21;
//这样写的话,文件里显示是乱码
fwrite(&s,sizeof(Stu),1,fp);
//因为是格式化输出,不是乱码
fprintf(fp,"%s %d",s.name,s.age);
2.一个结构体写入到文件里,查看文件,是乱码。 因为是二进制模式打开的,所以是乱码,所以使用格式化的打印,不会出现乱码的情况。
//写入成功,但是,此时文件里是乱码。
Stu *s1 = (Stu*)malloc(sizeof(Stu*));
s1->name = "tom";
s1->age = 21;
fwrite(s1,sizeof(Stu),1,fp);
3.一个结构体,写入到文件里,再读取出来。注意要光标重定位,否则会出现错误。
//写+读
Stu *s1 = (Stu*)malloc(sizeof(Stu*));
Stu *s2 = (Stu*)malloc(sizeof(Stu*));
s1->name = "tom";
s1->age = 21;
//往文件里写
fwrite(s1,sizeof(Stu),1,fp);
//重定位一下光标 很重要
rewind(fp);
//从文件中读取
fread(s2,sizeof(Stu),1,fp);
printf("%s %d\n",s1->name,s1->age);
printf("%s %d",s2->name,s2->age);
tom 21
tom 21
--------------------------------
Process exited after 0.03888 seconds with return value 0
请按任意键继续. . .
其他函数
- int feof(FILE *stream)
- 当到了文件结尾的时候,该函数返回一个非零值,否则返回零,判断的时候 !feof(FILE)就是没到结尾
- int ferror(FILE *stream)
- 当前的流出错,函数返回一个非零值,否则返回一个零值。if( ferror ){出错}
- void rewind(FILE *stream)
- 定位光标到开头
- int fseek(FILE *stream, long int offset, int whence)
- 改变当前光标的位置
- stream 文件流
offset 这是相对 whence 的偏移量,以字节为单位。
whence 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一:
SEEK_SET 文件的开头
SEEK_CUR 文件指针的当前位置
SEEK_END 文件的末尾
- long int ftell(FILE *stream)
- 返回光标当前位置。
- 这里面光标的意思就是文件指针。