按单个字符、行或指定对象(二进制)读写文件
读写流
流支持不同的读写方式:
1.读写一个字符:fgetc()/fputc()一次读/写一个字符
2.读写一行:fgets()和fputs()一次读/写一行
3.读写若干个对象:fread()/fwrite() 每次读/写若干个对象,而每个对象具有相同的长度
一、按字符输入和输出?
1.按单个字符输入(读取)
下列函数用来输入一个字符:
#include <stdio.h>
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
Ø 成功时返回读取的字符;若到文件末尾或出错时返回EOF
Ø getchar()等同于fgetc(stdin)
#include <stdio.h>
int main(int argc,char *argv[])
{
FILE *fp;
int ch,count = 0;
if((fp=fopen("1.txt","r"))==NULL)
{
perror("fopen");
return -1;
}
while((ch = fgetc(fp))!=EOF)
{
count++;
}
printf("total %d bytes\n",count);
return 0;
}
2.按单个字符输出(写入)
下列函数用来输出一个字符:
#include <stdio.h>
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
Ø 成功时返回写入的字符;出错时返回EOF(即-1)
Ø putchar©等同于fputc(c,stdout)
代码如下:
#include <stdio.h>
int main(int argc,char *argv[])
{
FILE *fp;
int ch;
if((fp=fopen("1.txt","r+"))==NULL)
{
perror("fopen");
return -1;
}
for(ch =‘a’; ch <=‘z’; c++)
{
fputc(ch, fp);
}
return 0;
}
二、按行输入输出
1.按行输入(从文件读取到缓冲区)
下列函数用来输入一行:
#include <stdio.h>
char *gets(char *s);//该函数默认从键盘输入,已经淘汰(容易造成缓冲区溢出)
char *fgets(char *s, int size, FILE *stream);
Ø 成功时返回s,到文件末尾或出错时返回NULL
Ø gets不推荐使用,容易造成缓冲区溢出
Ø fgets函数从文件FILE中获取某一行的size-1的字符数据,当遇到’\n’或已输入size-1个字符时返回,最后总是包含’\0’组成size大小的字符串,因此只能获取size-1个字符到缓冲区s
Ø 如果文件中的字符不够size-1个字符,并且最后一个字符是‘\n’,会将‘\n’也读取到缓冲区s中。
代码如下(示例):
#include <stdio.h>
int main(int argc,char *argv[])
{
FILE *fp;
char *ret;
char *buff;
if((fp=fopen("1.txt","r+"))==NULL)
{
perror("fopen");
return -1;
}
if((ret = fgets(buff,5,stdin))==NULL)//从键盘获取,如果想从文件中获取,只需要把stdin换成fp即可。
{
perror("fgets");
return -1;
}
printf("buff=%s\n",buff);
return 0;
}
2.按行输出(写入到文件)
下列函数用来输出字符串:
#include <stdio.h>
int puts(const char *s);
int fputs(const char *s, FILE *stream);
Ø 成功时返回输出的字符个数;出错时返回EOF
Ø puts将缓冲区s中的字符串输出到stdout,并追加’\n’
Ø fputs将缓冲区s中的字符串输出到stream
代码如下(示例):
#include <stdio.h>
int main(int argc,char *argv[])
{
FILE *fp;
int retn;
char buff[]="hello world";
if((fp=fopen("1.txt","w"))==NULL)
{
perror("fopen");
return -1;
}
if((retn = fputs(buff,stdout))==-1)//代码是将hello world打印到屏幕上,如果想写入到文件,只需要把stdout换成fp即可。
{
perror("fputs");
return -1;
}
printf("fputs success");
return 0;
}
//注意:输出的字符串中可以包含’\n’
,也可以不包含
按指定对象(二进制文件)的输入输出
下列函数用来从流中读写若干个对象:
#include <stdio.h>
**size_t fread(void ptr, size_t size, size_t n, FILE fp);
参数:
void *ptr 读取内容放的位置指针
size_t size 读取的字节大小 (size_t 就是int类型)
size_t n 读取size大小的个数
FILE *fp 读取的文件指针
**size_t fwrite(const void ptr, size_t size, size_t n, FILE fp);
参数:
void *ptr 写文件内容的位置指针
size_t size 写的字节大小 (size_t 就是int类型)
size_t n 写的size大小的个数
FILE *fp 要写的文件指针
Ø 成功返回读写的对象个数;出错时返回EOF
Ø 既可以读写文本文件,也可以读写数据文件
Ø 效率高
按指定对象的输入(读文本文件)
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
FILE *fp;
int ret;
char *buff;
if((fp=fopen("1.txt,","r"))==NULL)//如果想读取二进制文件可以把1.txt换成1.bin文件。
{
perror("fopen");
return -1;
}
buff =(char *)malloc(100);
if(buff==NULL)
{
return 0;
}
if((ret=fread(buff,10,1,fp))==-1)
{
perror("fread");
goto end;
}
printf("buff=%s\n",buff);
end:
free(buff);
fclose(fp);
}
按指定对象的输出(写入到文件)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student{
char name[16];
int age;
char sex[8];
};
int main(int argc,char *argv[])
{
FILE *fp;
int ret;
struct student stu;
struct student stu1;
if((fp=fopen("1.txt,","w"))==NULL)//如果想读取二进制文件可以把1.txt换成1.bin文件。
{
perror("fopen");
return -1;
}
strcpy(stu.name,"zhangsan");
stu.age = 61;
strcpy(stu.sex,"male")
if((ret=fwrite(stu,sizeof(stu),1,fp))==-1)
{
perror("fwrite");
goto end;
}
else
{
printf("fwrite success");
}
fclose(fp);//写完文件之后必须先关闭一下在读,因为文件指针指到了写文件的末尾
if((fp=fopen("1.bin,","r"))==NULL)
{
perror("fopen");
return -1;
}
if((ret=fread(stu1,sizeof(stu),1,fp))==-1)
{
perror("fread");
goto end;
}
printf("name=%s,age=%d,sex=%s",stu.name,stu.age,stu.sex);
end:
fclose(fp);
}
接下来会学习文件指针的移动来改进代码,就不用每次关闭文件了。