标准IO和文件IO的主要区别是:可移植性,缓存问题
文件的常见操作:
fopen/fclose
函数原型:
参数说明:
NULL表示打开失败
&模板:
int main(){
FILE *fp;
fp = fopen("aa.txt","r"); //r只读;r+可读写;w只写(清空已有文件内容);w+可读写
if(fp == NULL){
//当调用失败,做错误处理
/**
//第一种:
fprintf(stderr,"fopen failed\n"); //将失败返回提示打印到文件中
exit(0); //exit(main()) => exit(return 0)
//第二种:
fprintf(stderr,"%d\n",strerror(errno)); //strerror()返回错误编号
exit(EXIT_FAILURE);
*/
//第三种:
perror("fopen"); //分析错误原因
exit(EXIT_FAILURE);
//注意:“一般采用第三种配套语句进行打开文件的错误处理”
}
printf:("fopen success \n");
fclose(fp); //关闭文件
exit(EXIT_SUCCESS);
}
fgets/fputs
// fgets 可以读一行字符
用法:char buf[10]; fgets(buf,sizeof(buf),stdin);
原型:char *fgets(char *s,int *size,FILE *stream);
(stream: stdin标准输入、stdout标准输出、stderr标准错误)
不会导致段错误,如果超出限定空间就自动去掉多余部分
&练习:编写一个程序,统计一个文件内容的行数:
int main(int argc,char *argv[]){
if(argc != 2){
fprintf(stderr,"too few arguement\n")
}
FILE *fp = fopen(argv[1],"r");
if(fp == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
char buf[100];
int line = 0;
while(fgets(buf,sizeof(buf),fp) != NULL){
line++;
pritnf("%s\n",buf);
}
printf("line=%d\n",line);
fclose(fp);
exit(EXIT_SUCCESS);
}
fgetc/fputc
// fgetc 可以读一个字节
函数原型:
&练习1:编写一个程序,将一个文件的内容拷贝到另一个文件里面去
int main(int argc,char *argv[]){
if(argc != 3){
fprintf(stderr,"too few arguement\n");
exit(EXIT_FAILURE);
}
FILE *in,*out;
in = fopen(argv[1],"r");
if(in == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
out = fopen(argv[2],"w");
int ch;
while((ch = fgetc(in)) != EOF){
fputc(ch,out);
}
fclose(in);
fclose(out);
exit(EXIT_SUCCESS);
}
&练习2:编写一个文件test.txt,每隔一秒向文件中写入数据,如图:
int main(int argc,char **argv){
if(argc != 2){
fprintf(stderr,"too few arguement\n");
exit(EXIT_FAILURE);
}
FILE *fp = fopen("argv[1]","a+");
int len = 0;
char buf[100];
while(fgets(buf,sizeof(buf),fp) != NULL)
len++;
time_t t;
struct tm *p;
while(1){
time(&t);
p=localtime(&t);
len++;
fprintf(fp,"%d,%d-%d-%d %d:%d:%d\n",len,p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec);
fflush(fp);
sleep(1);
}
//fclose(fp);
exit(EXIT_SUCCESS);
}
fwrite/fread
// fread 可以任意读(从文件流中读数据)
函数原型:
- fread(读入什么地方,每次读几个字节,读多少次,在哪(文件)读)
- fwrite(写入的内容首地址,每次写多少个字节,写几次,写入的文件)
- 数据类型:size_t 可以是整形int,但做long最稳定;说白了就应该是 unsigned long。
- 返回值:返回实际写入的数据块数目
(1)ptr:是一个指针,对fwrite来说,是要获取数据的地址;
(2)size:要写入内容的单字节数;
(3)nmemb:要进行写入size字节的数据项的个数;
(4)stream:目标文件指针;
(5)返回实际写入的数据项个数nmemb。 - 注意:写入到文件的哪里?
这个与文件的打开模式有关,如果是w+,则是从file pointer指向的地址开始写,替换掉之后的内容,文件的长度可以不变,stream的位置移动nmemb个数;如果是a+,则从文件的末尾开始添加,文件长度加大。 - 例子:
int main(void)
{
FILE *fp;
char msg[]="hello";
char buf[20];
if((fp = fopen("test.txt","w+"))==NULL)
{
perror("fopen");
exit(EXIT_FAILURE);
}
//向文件中写入一些数据
fwrite(msg,sizeof(char),sizeof(msg),fp);
//sizeof(char)=1 回到文件的开头位置
fseek(fp,0,SEEK_SET); //rewind(fp)
//读出数据并显示
fread(buf,sizeof(msg),1,fp);
printf("%s\n",buf);
fclose(fp);
return 0;
}
rewind()、fseek()
- fseek 重定位流(数据流/文件)上的文件内部位置指针
- 注意:文件指针指向文件/流。位置指针指向文件内部的字节位置,随着文件的读取会移动,文件指针若不重新赋值将不会改变或指向别的文件。
该函数和lseek函数类似,但lseek返回的是一个off_t数值,而fseek返回的是一个整型。 - 参数说明:stream文件指针;offset表示偏移量;whence设定文件从哪里开始偏移。whence的可能取值为:SEEK_SET文件开头,SEEK_CUR当前位置,SEEK_END文件结尾。