Linux流编程

与文件编程相比,基于流的IO方式最大特点就是先对缓冲区进行操作,具有较高的操作效率。流的操作过程与基于文件描述符的I/O操作过程十分类似:对流进行读写、定位操作等,最后关闭流。

在Linux中,对于流的打开就是建立一个缓冲区,将这个缓冲区和对应的文件相关联的过程,Linux提供了fopen、fdopen、freopen等函数来完成相应的操作,调用fclose函数会将流中的数据写入对应的文件中,并且清除整个缓冲区。

/*
	Name: 
	Copyright: 
	Author: Li Jiansong 
	Date: 08/10/15 08:59
	Description: 
	调用fopen打开argv[1]所指向的文件,如果没有改文件则创建,然后关闭这个流 
*/

#include<stdio.h>

int main(int argc,char *argv[])
{
	FILE *fp;
	int iflag;
	if(argc<=1)
	{
		printf("usage: %s filename\n",argv[0]);
		return 1;
	}
	fp=fopen(argv[1],"a+b");
	if(fp==NULL)
	{
		printf("open file %s failed!\n",argv[1]);
		return 2;
	}
	printf("open file %s succeed!\n",argv[1]);
	iflag=fclose(fp);
	if(iflag==0)
	{
		printf("close file %s succeed!\n",argv[1]);
		return 0;
	}
	else{
		printf("close file %s failed!\n",argv[1]);
		return 3;
	}
}

对于流的缓冲方式和缓冲区设置,Linux也提供了相关的函数。流的缓冲方式有3种:全缓冲,在这种方式下,直到缓冲区被填满,才使用系统调用进行操作,Linux内核中使用宏_IO_FULL_BUF来表示全缓冲;行缓冲,在这种方式下,遇到换行符才使用系统调用进行操作;无缓冲,这种方式下,不进行缓冲,数据会立即读入或者输出到外存文件和设备上。

Linux中的流最终都是需要对应到具体的文件,所以每个流都有对应的文件描述符,可以对流调用fileno函数来获得流对应的文件描述符。对于流的缓冲区设置,如果需要对Linux内核提供的流缓冲状态进行修改,可以调用setbuf、setvbuf、setbuffer、setlinebuf、setlinebuf等系列函数。

/*
	Name: 
	Copyright: 
	Author: Li Jiansong 
	Date: 08/10/15 08:59
	Description: 
	打印3个标准流和一个关联到普通文件的流缓冲状态 
*/

#include<stdio.h>
#include<stdlib.h>

#if defined(MACOS)
#define _IO_UNBUFFERED __SNBF
#define _IO_LINE_BUF __SLBF
#define _IO_file_flags _flags
#define BUFFERSZ(fp) (fp)->_bf._size
#else
#define BUFFERSZ(fp) ((fp)->_IO_buf_end -(fp)->_IO_buf_base)
#endif 

void pr_stdio(const char*,FILE *);//缓冲输出函数 
int main(int argc,char *argv[])
{
	FILE *fp;
	printf("please enter some str:\n"); 
	if(getchar()==EOF)
	{
		perror("getchar error\n");
	}
	fputs("one line to standard error\n",stderr);
	
	pr_stdio("stdin",stdin);
	pr_stdio("stdout",stdout);
	pr_stdio("stderr",stderr);
	perror("fopen error");
	if(getc(fp)==EOF)
		perror("getc error");
	pr_stdio("/etc/motd",fp);
	exit(0);
}
void pr_stdio(const char *name,FILE *fp)
{
	printf("stream = %s,",name);
	if(fp->_IO_file_flags & _IO_UNBUFFERED)
		printf("unbuffered");
	else if(fp->_IO_file_flags & _IO_LINE_BUF)
		printf("line buffered");
	else
		printf("fully buffered");
	printf(",buffer size = %d\n",BUFFERSZ(fp));
}


对流的操作的主要目的就是对流所指定的文件进行读写,对流的读写操作主要有3种:字符读写,每次读写一个字符数据;行读写,当遇到换行符的时候,则将流中换行符之前的内容送到缓冲区中,每次读写一行;块读写,以块为单位进行读写。对于字符读写,可以调用getc、fgetc、getchar等系列函数来完成。对于行读写,可以调用gets、fgets、puts、fputs等系列函数。在读写操作中,如果需要操作的区域多余一个字符或者多余一行,使用字符读写和行读写都比较麻烦,并且在一行数据中包括了NULL字符也会导致行操作的终止,此时可以调用二进制(按块/结构)读写函数,此时可以调用fread、fwrite等系列函数。在关闭流或者完成相应的操作以后应该将缓冲区的数据清空,Linux提供了fflush和_fpurge等函数来完成流的清洗。

/*
	Name: 
	Copyright: 
	Author: Li Jiansong 
	Date: 08/10/15 08:59
	Description: 
	字符读写 
*/

#include<stdio.h>
#include<errno.h>

int main(int argc,char *argv[])
{
	int c;
	printf("please enter some str, CTRL+D for stop!\n");
	while((c=getc(stdin))!=EOF)
	{
		if(putc(c,stdin)==EOF)
		{
			perror("output error");
		}
	}
	if(ferror(stdin))
		perror("input error");
	return 0;
}

#include<stdio.h>
int main()
{
	char s[80];
	fputs(fgets(s,80,stdin),stdout);
    return 0;
}

对于流的定位,有3种方式:使用ftell和fseek函数,必须假设偏移量可以放到一个长整型中,针对这两个函数,Linux还提供了rewind函数用于将偏移量设置到流的起始部分;ftello和fseeko函数,使用了off_t数据类型代替长整型;fgetpos和setpos函数,使用一个抽象数据类型fpos_t来记录文件的位置,该数据类型可以定义为一个文件位置所需要的长度。

#include<stdio.h>
int main()
{
	FILE * stream;
	long offset;
	fpos_t pos;
	stream=fopen("/etc/passwd","r");
	fseek(stream,5,SEEK_SET);
	printf("offset=%d\n",ftell(stream));
	rewind(stream);
	fgetpos(stream,&pos);
	printf("offset=%d\n",pos);
	pos=10;
	fsetpos(stream,&pos);
	printf("offset = %d\n",ftell(stream));
	fclose(stream);
    return 0;
}

此外,Linux内核允许用户建立并使用临时文件。临时文件可以存放计算的中间结果,也可以在关键操作之前用于数据备份。可以使用函数tmpnam、tempnam、tmpfile等来完成该操作。

/*
	Name: 
	Copyright: 
	Author: Li Jiansong 
	Date: 08/10/15 08:59
	Description: 
	利用tmpfile创建并打开一个临时文件,并且写入一行数据,随后将其读出并写入到标准输出 
*/

#include<stdio.h>
#include<errno.h>
#include<stdlib.h> 

int main(int argc,char *argv[])
{
	FILE *tempfp;
	char line[256];
	
	tempfp=tmpfile();//获得文件名 
	if(tempfp==NULL)
	{
		perror("tmpfile error!\n");
		return 1;
	}

	printf("open a tmp file succeed!\n");
	fputs("test for tempfile\n",tempfp);
	rewind(tempfp);

	if(fgets(line,sizeof(line),tempfp)==NULL)
	{
		printf("fgets error!\n");
		return 2;
	}

	fputs(line,stdout);
	return 0;
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值