在shell应用中,重定向的操作就是修改了输入/输出流。
一、ANSI C文件IO管理
1.读写文件流
根据应用的不同需要,ANSI 标准提供了3种类型的I/O处理函数,包括字符读写,行读写和块读写。如果使用了缓冲区,则不需要每次进行标准IO处理时都使用系统调用,至于什么时候使用系统IO调用则由缓冲区类型及缓冲区中的数据量决定
(1)字符读写文件流
1>.字符读操作
int fgetc(FILE *_stream)返回内容
int getc(FILE *_stream)
getcahr()相当于fgetc(stdin);
成功返回内容,失败则返回-1
2>.字符写操作
int fputc (int _c,FILE _stream);
int putc (int _c,FILE *_stream);
putchar()相当于fputc(c,stdout)
成功返回内容,失败则返回-1
#include<stdio.h>
int main(int argc,char *argv[])
{
FILE *fp=NULL;
char ch;
if(argc<=1)
{
printf("check usage of %s \n",argv[0]);
return -1;
}
if((fp=fopen(argv[1],"r"))==NULL)
{
printf("can not open %s\n",argv[1]);
return -1;
}
while ((ch=fgetc(fp))!=EOF)
fput(ch,stdout);
fclose(fp);
return 0;
}
(2).行读写文件流
1>.行读出操作。
char *fgets(char *restrict _s,int _n,FILE *_restrict _stream)
2>.行写入操作。
int fputs(_const char *_restrict _s,FILE *_restrict _stream);
int puts(_const char *_s);//把s写入stdin,后接换行符。
失败返回-1。
#include<stdi.h>
int main(int argc,char *argv[])
{
FILE *fp=NULL;
char str[10];
if ((fp=fopen(argv[1],"r"))==NULL)
{
printf("can not open!\n");
return -1;
}
fgets(str,sizeof(str),fp);
fputs(str,stdout);
fclose(fp);
return 0;
}
(3).块读写文件流。
指的是每次读出与写入的数据量可以由编程人员设定。
1>.块读出操作。
size_t fread(void *_restrict _ptr,size_t _size,size_t _size,size_t _n,FILE *_retrict _stream);
功能:从流中读取n个大小为size的对象存放于ptr所指向的内存空间。
参数:1.存放地址,2.要读取的对象大小 3.要读取的对象个数 4.流
返回值:实际读取到的对象个数
2>.块写入操作。
size_t fwrite (_const void _restrict _ptr,size_t _size ,size _t _n,FILE _restrict _s)
#include<stdio.h>
int main(int argc,char *argv[])
{
struct student
{
char name[10];
int number;
};
FILE *fp=NULL;
int i;
struct student boya[2],boyb[2],*pp,*qq;
if((fp=fopen("aa.txt","w+"))==NULL)
{
printf("can not open!\n");
return -1;
}
pp==boya;
qq==bbyb;
printf("please input two students' name and number:\n");
for(i=0;i<2;i++,pp++)
scanf("%s\t%d",pp->name,&pp->number);
pp=boya;
fwrite(pp,sizeof(struct student),2,fp);
rewind(fp);
fread(qq,sizeof(struct student),2,fp);
printf("name\t\t number\n");
for(i=0;i<2;i++,qq++)
printf("%s\t\t %d\n",qq->name,qq->number);
fclose(fp);
return 0;
}
(4)文件流检测
1>.
对于ASCII码文件,可以通过简单地判断来确定是否读到了流的结束,如果读到-1,则肯定读到了结束。
但对于二进制文件,如果fread读到了文件尾部或者出错,将使用feof()函数检测。
int feof (FILE *_stream)
如果读到文件结束,返回1,否则返回0.
2>
int ferror(FILE* _stream)
int ferror(FILE *_stream)
使用feof或ferror进行判断,如果出现错误,将设置错误标志位,执行错粗处理后应该清除错误标识位。
(5)文件流定位
1>.返回当前读写位置
long int ftell(FILE*_stream)
返回值:成功,则当前指针位置距离文件开始的字节数,如果失败,则返回-1;
2>.修改当前读写位置
int fseek(FILE *_stream,long int _off,int _whence);
参数:1.流 2.为针对第三个参数(修改基准)的偏移量
3.修改位置的基准,共三个:
#define SEEK_SET 0 //文件开始位置
#define SEEK_CUR 1 //当前位置
#define SEEK_END 2 //文件结束位置
返回值:成功0,失败-1.
3>重置当前读写位置到文件开头。
void rewind (FILE *_stream);
#include<stdio.h>
int main()
{
struct student
{
char name[10];
int number;
};
FILE *fp=NULL;
struct student student[1],*qq;
if((fp=fopen("aa.txt","r"))==NULL)
{
printf("can not open file!\n");
return -1;
}
fseek(fp,sizeof(struct student),SEEK_SET);
fread(student,sizeof(struct student),1,fp);
printf("name\t\t number\n");
qq=student;
printf("%s\t\t %d\n",qq->name,qq->number);
fclose(fp);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
int n=0;
FILE *fp;
if((fp=fopen(argv[1],"r"))==NULL)
{
perror("fopen");
exit(EXIT_FAILURE);
}
if(fseek(fp,0,SEEK_END)!=0)
{
perror("fseek");
exit(EXIT_FAILURE);
}
if((n=ftell(fp))==-1)
{
perror("ftell");
exit(EXIT_FAILURE);
}
printf("the size count by fseek/ftell of the file is %d\n",n);
printf("this is ls output:\n");
execl("/bin/ls","ls","-1",argv[1],(char *)0);
fclose(fp);
}
(6)fprintf/fscanf函数分析
fprintf()和fscanf()函数可用于任意流。
fprintf()将输出按指定格式放置在指定的输出流上。
int fprintf(FILE ,const char ,…);
fscanf()从指定的输入流中按指定格式读取数据。
int fscanf(FILE ,const char );
fprintf(fp,"%s",buf)//输出到文件
fscanf(fp,"%s",buf);//从文件读取字符串
(7)sprintf函数分析
sprintf()主要针对字符串的操作,同样是变参函数:
int sprintf( char *buffer,const char *format,artument…);
功能:sprintf是将列出的数据或者变量以format格式输出到以buffer为起始位置的内存空间中。
sprintf(s,"%s love %s","I","English");//s变为“I love English”