文件及文件流

1、文件与流的基本概念
在Linux系统下,除了常规的文件外,目录,设备,管道等也属于文件。
根据文件的存储方式,我们可以将文件分为两类,二进制文件以及文本文件。
(1)文本文件:ASCII文件,每个字节存放一个ASCII码字符,文本文件存储量大,速度慢,便于对字符操作,以EOF结尾。
(2)二进制文件:数据按其在内存中的存储形势原样存放,存储量小,速度快,便于存放中间结果。
根据对文件的访问方式又分为带缓冲区文件和不带缓冲区文件。
(1)带缓冲:高级文件操作,将在用户空间中自动生成缓冲区(缓冲区具有快速存取的能力,方便我们对数据的操作,提高磁盘的访问速度)
(2)不带缓冲区:低级文件操作,如果需要,只能由用户自己在程序中为每个文件设定缓冲区。
2、标准流及流的主要功能
在Linux系统中有,系统会默认给每个进程打开三个文件,即标准输入流(对应文件/dev/stdin),标准输出流(/dev/stdout),标准错误输出流(/dev/stderr).这是三个流指针及宏定义如下:
在这里插入图片描述
3、文件流指针
程序在对文件进行操作时,我们会使用到文件流指针FILE,在操作之前我们要打开文件,可以自定义打开的权限,如读,写等。我们用到fopen函数来打开一个文件后,将返回 一个文件流指针,我们就是对该文件流指针来进行文件的一些操作。
4缓冲区类型
(1)全缓冲区:这种缓冲区默认大小为BUFSIZ,具体大小与系统定义有关。在缓冲区满或者调用刷新函数ffush()函数时才进行I/O操作。用于普通磁盘文件。
(2)行缓冲区:当在遇到换行符或者缓冲区满时,行缓冲区才刷新。
(3)不带缓冲:不对字符进行缓存。
标准输入和标准输出设备:当前仅当不涉及交互式作用设备时,标准输入流和标准输出流才是全缓冲区
标准错误输出设备:标准出错绝不会是全缓冲区的。下面是一个测试缓冲区类型的应用程序。
#include<stdio.h>
void pr_stdio(const char *, FILE *); //声明函数
int main()
{
FILE *fp; //文件流指针
fputs(“enter any character\n”,stdout);
if (getchar()==EOF)
printf(“getchar error”);
fputs(“one line to srandard error\n”,stderr);
pr_stdio(“stdin”,stdin); //测试标准输入流
pr_stdio(“stdout”,stdout); //测试标准输出流
pr_stdio(“stderr”,stderr); //测试标准错误流
if((fp=fopen("/4/test_one",“r”))==NULL) //普通文件,并打开为只读文件
printf(“fopen error”);
if(fgetc(fp)==EOF)
printf(“getc error”);
pr_stdio("/4/test_one",fp);
return 0;
}
void pr_stdio(const char *name,FILE *fp)
{
printf(“strem=%s”,name);
if (fp->_flags & _IO_UNBUFFERED) //是否为无缓冲
printf(“unbuffered”);
else if(fp->_flags & _IO_LINE_BUF) //是否为行缓冲
printf(“line buffer”);
else //其他情况,全缓冲或者自定义缓冲类型
printf(“fully buffer or modified”);
printf(",buffer size = %d\n",fp->_IO_buf_end-fp->_IO_buf_base);
}
其执行结果如下:
在这里插入图片描述
该程序对普通文件的标准输入标准输出和标准输入和标准错误进行了判断。打印的结果是标准输入和输出都是行缓冲,标准错误流无缓冲。
5指定缓冲区
如果用户希望自己设置缓冲区位置,或者说对默认位置不满意,我们可以使用setbuf(),setvbuf()函数进行缓冲区的指定和修改。函数声明如下。
在这里插入图片描述
在这里插入图片描述
如果指定一个不带缓冲区的流,则不用写buf,size参数。
下面是一个指定流缓冲区的应用示例:
#include<stdio.h>
#include<error.h>

int main()
{
int i;
FILE *fp;
char m1[]=“hello,wolrd\n”;
char m2[]=“hello\nworld”;
char buf[128];
if((fp=fopen(“no_buf1.txt”,“w”))==NULL) //打开为只读
{
perror(“dile open failure!”);
return (-1);
}
setbuf(fp,NULL); //设置为无缓冲
memset(buf,’\0’,128); //清空buf数组
fwrite(m1,7,1,fp); //对文件进行写入
printf(“test setbuf(no buf)!cheak no_buf1.txt\n”); //查看缓冲区当前数据
printf(“now buf data is :buf=%s\n”,buf); //无缓冲区,所以无输出
printf(“press enter to continue!\n”);
getchar(); //获取一个字符串
fclose(fp); //关闭流
if((fp=fopen(“no_buf2.txt”,“w”))==NULL)
{
perror(“dile open failure!”);
return (-1);
}
setvbuf(fp,buf,_IONBF,0); //改变缓冲类型,为无缓冲区
memset(buf,’\0’,128);
fwrite(m1,7,1,fp);
printf(“test setbuf(no buf)!cheak no_buf2.txt\n”);
printf(“now buf data is :buf=%s\n”,buf); //无缓冲区,无输出
printf(“press enter to continue!\n”);
getchar();
fclose(fp);
if((fp=fopen(“l_buf.txt”,“w”))==NULL)
{
perror(“dile open failure!”);
return (-1);
}
setvbuf(fp,buf,_IOLBF,sizeof(buf)); //设置为行缓冲
memset(buf,’\0’,128);
fwrite(m2,sizeof(m2),1,fp);
printf(“test setbuf(line buf)!cheak l_buf.txt, because line buf, only data before enter send to file\n”);
//因m2中有\n换行符,对于行缓冲来说只能读取一行,所以打印一行的信息
printf(“now buf data is :buf=%s\n”,buf);
printf(“press enter to continue!\n”);
getchar();
fclose(fp);
if((fp=fopen(“f_buf.txt”,“w”))==NULL)
{
perror(“dile open failure!”);
return (-1);
}
setvbuf(fp,buf,_IOFBF,sizeof(buf));
memset(buf,’\0’,128);
fwrite(m2,sizeof(m2),1,fp);
printf(“test setbuf(no buf)!cheak f_buf.txt, because line buf, only data before enter send to file\n”);
printf(“now buf data is :buf=%s\n”,buf);
printf(“press enter to continue!\n”);
getchar();
fclose(fp);

}
下面是执行端结果(图1),在执行过程中我们同时查看文件内容(图2)。
在这里插入图片描述
在这里插入图片描述
有结果我们可以看到,当我们有缓冲区时,一些数据在缓冲区中还没有完全进入文件中,所以我们看到第一个文件以及第二个文件,在执行时就已经全部写入文件中了,所以在输出时,缓冲buff什么都没有得到(无缓冲区,所以没有缓冲内容)。而第三个文件中只有第一行的数据,没有第二行的数据,因为行缓冲区只保留一行的数据。我们写入文件时是先写入第一行,一开始行缓冲区中是刚进入缓冲区的第一行数据,当读取到\n时进入了第二行,这时行缓冲去的数据写入文件中,第二行的数据保存在行缓冲区中,这就是为什么缓冲区中的数据是最后一行。
在(图2)中我们看到只有hello,而world保存在行缓冲区中。对于第四个全缓冲区来说,他的所以数据在程序执行过程中都是保存在缓冲区中,所以图二中查看时文件为空。
在程序完全执行完成后,缓冲区全部清空,所有数据全部写入文件,在查看时所有数据都保存在文件中。此时释放缓冲!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值