0、前言
文件按数据在文件中的存储形式,分为文本文件,即文件中的字符都是以ASCII码的形式存储;
如3.14 以文本文件形式存储,每个字符占一个字节,共占4个字节;
二进制文件,是将数据按其在内存中的存储形式(二进制码)的形式存储的。
如3.14以二进制文件存储,用float类型占4个字节,用double类型占8个字节。
本文讨论以文本文件形式存储的各个函数。以二进制形式存储文件参见该文。
参考文章:https://blog.csdn.net/strongwangjiawei/article/details/7786085/
经常用的函数:
打开文件 | 读写字符串 | 读写字符 | 向标准输入输出 读写字符 | 读写任意 形式字符 | 向标准输入输出 读写任意形式字符 | 关闭文件 |
fopen | fgets | fgetc | getchar | fscanf | scanf | fclose |
fputs | fputc | putchar | fprintf | printf |
1、文件打开
#include <stdio.h>
FILE * fopen(char *filename,char *type);
filename:文件名
type:打开方式
打开方式 :
"r" 打开只读文件;文件必须存在
"w" 打开只写文件,指针指到头;若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。
"a" 打开只写文件,指向文件尾,在已存在文件中追加;若文件不存在,则会创建该文件;若文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF 符保留)。
"r+" 以读/写方式打开一个已存在的文件;文件必须存在,从文件开头写,保留文件中没有被覆盖的内容。
"w+" 以读/写方式建立一个新的文本文件 ;若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。
"a+" 以读/写方式打开一个文件文件进行追加 ;若文件不存在,则会创建该文件,若文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF符不保留)。
注意:无论是“w”或者"w+",都会将原文件中的数据清除。详细区别见本文。
小结:r+,w+,a+三者的属性都是在r,w,a的属性基础上叠加的,首先都具备了r,w,a的属性,即:
r+,首先具有r的可读,文件必须存在的属性,有了+后,增加了w的从文件头开始覆盖的写属性;
w+,首先具有w的清空原文件内容写属性,文件不存在就创建的属性,有了+后,增加了读属性;
a+,首先具有a的在原文件后增加内容写属性,文件不存在就创建的属性,有了+后,增加了读属性。
以上三个加号,都是可读可写的属性,需要注意的是,在先写了数据后,文件中的指针是指向了最后一个字节的下一个字节的位置的,如果要重文件的开头开始读数据,需要先用fseek函数将指针移到开头位置,fseek(fp,0,SEEK_SET);先读后写同理。
ps:感觉,w+完全可以替代r+......
*************************************************************************************
"rb" 打开一个二进制文件,只读;
"wb" 打开一个二进制文件,只写;
"ab" 打开一个二进制文件,进行追加 ;
"rb+" 以读/写方式打开一个二进制文件;
"wb+" 以读/写方式建立一个新的二进制文件 ;
"ab+" 以读/写方式打开一个二进制文件进行追加 ;
返回值:
成功返回一个FILE指针;失败,返回一个NULL指针。
注意:r模式的时候,首先要先创建一个filename文件,否则会报如下错误:
2、文件关闭
int fclose(FILE *stream);
关闭文件,使文件指针变量不在指向该文件,释放指针变量。
文件打开并读写操作完成后,需要将文件进行关闭。
成功返回0,失败返回非0值。
当打开多个文件进行操作,而又要同时关闭时,可采用fcloseall()函数,它将关闭所有在程序中打开的文件。 int fcloseall(); 该函数将关闭所有已打开的文件,将各文件缓冲区未装满的内容写到相应的文件中去,接着释放这些缓冲区,并返回关闭文件的数目。如关闭了4个文件,则当执行: n=fcloseall(); 时,n应为4。
3、读写文件
3.1每次仅读写一个字符
int fgetc(FILE *stream); //从文件中读字符file get char //常用
成功返回读到的字符,失败或者读到文件末尾返回EOF;
EOF 是 end of file 的缩写,表示文件末尾,是在 stdio.h 中定义的宏,它的值是一个负数,往往是 -1。
EOF其实就是一个宏
#define EOF (-1)
注意:fgetc()的返回值是需要赋值给int型变量。
原因参照本文
int ch; //这个地方一定要是int才行!!!!!
while ( ( ch= fgetc(fp) ) != EOF) //不断读取文件直到结束
{
putchar(ch);
}
int fputc(int ch,FILE *stream); //向文件中写字符 file put char //常用
成功时返回写入的字符,失败时返回 EOF,返回值类型为 int 也是为了容纳这个负数。
char ch = 'a';//输入char类型
fputc(ch,fp);
注意:fputc()函数实际应用中,我们可以传入char类型。
具体使用例程见本文
*************************************************************************************
int getchar(void); //getchar()相当于fgetc(stdin),即从标准输入中读取
int putchar(int ch); //putchar(c)相当于fputc(c,stdout),即输出到标准输出中
int getc(FILE *stream);
int putc(int ch,FILE *stream);
其中fgetc函数是每次只能读一个字符,当文件指针指向文件末尾时,此时为文件结束标志EOF(end of file)
,对应的值为-1,文件读取结束
int ch;
while((ch=fgetc(fp))!=EOF)
fputc(ch,stdout);
//因为是向标准输出中输出,故此处可以换成putchar(ch);
注意:
1)while循环体里并没有对文件指针fp的移动,也就是说在读取了一个一个字符后,fgetc函数对fp进行了++操作。
2)fgetc的返回值是int型,fputc的输入也是int,不要写错了。(也就是说,读取文件的时候,对字符进行了atoi()操作?)
man 手册中关于fputs的描述:
DESCRIPTION
fputc() writes the character c, cast to an unsigned char, to stream.
也就是说这里的int c,是将一个字符,强制转换成一个无符号的整形,然后读取的。
3.2每次读写字符串
char *fgets(char *string,int n,FILE *stream);
int fputs(char *string,FILE *stream);
int fscanf(FILE *stream,char *format,variable-list);//从文件中读取值并赋给变量,类比scanf从标准输入中读取 (cin>>a)
int fprintf(FILE *stream,char *format,variable-list);//输出变量到文件,类比printf输入到标准输出中,可以将整型变量等非字符变量输入到文件中,更加灵活。(可以类比cout<<a或者与fputc都是p开头或者类比sprintf函数等方式记忆。)
*************************************************************************************
char *gets(char *s);//废弃
char *puts(char *s);//废弃
其中fgets()是把由流指针指定的文件中的n-1个字符,读到string指向的字符数组中。也就是说,可能没读满一整行。
fgets()读到‘\n’就停止,而不论是否达到数目要求。同时再读取的字符串后加'\0',也就是说,正常情况是“****\n\0”
fgets()执行结束后,返回一个指向该串的指针。如读到文件尾或出错,则返回空指针(NULL);
char str[128];
while(!feof(fp)) {
if(fgets(str,128,fp)!=NULL)
printf("%s",str);
}
与fgetc()一样,fgets读取一次(行)后,文件流指针fp后移。
上述代码可以通过返回值来判断,简写为:
while(fgets(str,128,fp))
printf("%s",str);
fputs()是将string字符串写入到文件中,不包括'\0'
#include <stdio.h>
#include <stdlib.h>
int main() {
char *s="That's good news";
int i=617;
FILE *fp;
fp=fopen("test.dat", "w"); /*建立一个文字文件只写*/
fputs("Your score of TOEFL is",fp); /*向所建文件写入一串字符*/
fputc(':', fp); /*向所建文件写冒号:*/
fprintf(fp, "%d\n", i); /*向所建文件写一整型数*/
fprintf(fp, "%s", s); /*向所建文件写一字符串*/
fclose(fp);
}
#include <stdio.h>
int main() {
char s[24], m[20];
int i;
FILE *fp;
fp=fopen("test.dat", "r"); /*打开文字文件只读*/
fgets(s, 24, fp); /*从文件中读取23个字符*/
printf("%s", s);
fscanf(fp, "%d", &i); /*读取整型数*/
printf("%d", i);
putchar(fgetc(fp)); /*读取一个字符同时输出*/
fgets(m, 17, fp); /*读取16个字符*/
puts(m); /*输出所读字符串*/
fclose(fp);
}