APUE笔记四

1. 缓冲区

    标准I/O提供了三种类型的缓冲:

1) 全缓冲:在填满标准I/O缓冲区后才进行实际I/O操作。

2) 行缓冲:输入和输出遇到换行符的时候,标准I/O执行I/O操作。

3) 不带缓冲

    通常,系统默认的是:

1) 标准出错是不带缓冲的

2) 如若是涉及终端设备的其他流,则它们是行缓冲的;否则是全缓冲的。

#include <stdio.h>

void pr_stdio( const char *, FILE * );

int main( void )
{
        FILE    *fp;
        fputs("enter any character\n", stdout );
        if ( getchar() == EOF )
                printf("getchar error\n");
        fputs("one line to standard error\n", stderr );

        pr_stdio("stdin",stdin);
        pr_stdio("stdout",stdout);
        pr_stdio("stderr",stderr);

        if ( ( fp = fopen("/etc/xml", "r")) == NULL)
                printf("fopen error\n");
        pr_stdio("/etc/xml", fp);
        return 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", fp->_IO_buf_end - fp->_IO_buf_base );
}

程序输出:

备注:注意缓冲由“行缓冲”变为“全缓冲”。


2. 读和写流

1) 每次一个字符的读写流

#include <stdio.h>

int main( void )
{
        int     c;
        FILE *fp1 = fopen("temp", "r" );
        FILE *fp2 = fopen("temp.foo", "w ");
        if ( NULL == fp1 || NULL == fp2 ){
                printf("fopen error\n");
                return 1;
        }
        while ( ( c = getc( fp1 ) ) != EOF ){
                if ( putc( c, fp2 ) == EOF ){
                        printf("write file error\n");
                }
        }
        if ( ferror( fp1 ) ){
                printf("input error\n");
                clearerr( fp1 );
        }

        return 0;
}
 程序输出:


2) 每次一行字符读写流

#include <stdio.h>

int main( void )
{
        char    buf[ 10 ];
        FILE *fd1 = fopen("temp", "r");
        FILE *fd2 = fopen("temp.foo","w");
        if ( NULL == fd1 || NULL == fd2 ){
                printf("open file error\n");
                return 1;
        }
        while ( fgets( buf, 10, fd1 ) != NULL ){
                if ( fputs( buf, fd2 ) == EOF ){
                        printf("write error\n");
                        return 1;
                }
        }

        return 0;
}

3) 读取二进制文件

    这时候就不能使用getc/putc,fgets/fputs。我们通常需要一次读写整个结构。

size_t fread( void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp );
size_t fwrite( const void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp );
1--读写一个二进制数组。例如,为了将一个浮点数组的第2~5个元素写至一个文件上,则代码如下:

float data[ 10 ];
if (fwrite(&data[2], sizeof(float), 4, fp ) != 4 )
    printf("write error\n");

2--读写一个结构,则代码如下:

struct {
    short count;
    long total;
    char name[ NAMESIZE ];
} item;
if ( fwrite(&item, sizeof(item), 1, fp ) != 1  )
    printf("write error\n");

    以下程序将结构写入文件中,然后复制文件再读取出来:

#include <stdio.h>

struct people{
	char	*name;
	int	age;
};
int main( void )
{
	int	c;
	char	buf[ 10 ];
	FILE *fp1 = fopen("people", "w+");
	FILE *fp2 = fopen("people.foo","w+");
	if ( NULL == fp1 || NULL == fp2 ){
		printf("open file error\n");
		return 1;
	}
	struct people p1;
	struct people p2;
	struct people p3;
	struct people p4;
	p1.name = "小雷";
	p1.age = 25;
	p2.name = "小猫咪";
	p2.age = 24;

	if ( fwrite(&p1, sizeof( p1 ), 1, fp1 ) != 1 ){
		printf("write error\n");
		return 1;
	}
	if ( fwrite( &p2, sizeof( p2 ), 1, fp1 ) != 1 ){
		printf("write error\n");
		return 1;
	}
	
	if ( fseek( fp1, 0, SEEK_SET ) != 0 ){
		printf("fseek error\n");
		return 1;
	}	
	while ( ( c = getc( fp1 ) ) != EOF ){
		if ( putc( c, fp2 ) == EOF ){
			printf("write error\n");
			return 1;
		}
	}
//	while ( fgetc( buf, 10, fp1 ) != NULL ){
//		if ( fputs( buf, fp2 ) == EOF ){
//			printf("write file error\n");
//			return 1;
//		}
//	}

	if ( fseek( fp2, 0, SEEK_SET ) != 0 ){
		printf("fseek error\n");
		return 1;
	}
	if ( fread( &p3, sizeof( p3 ), 1, fp2 ) != 1 ){
		printf("read error\n");
		return 1;
	}
	if ( fread( &p4, sizeof( p4 ), 1, fp2 ) != 1 ){
		printf("read error\n");
		return 1;
	}
	printf("name is:%s, age is:%d\n", p3.name, p3.age );
	printf("name is:%s, age is:%d\n", p4.name, p4.age );

	return 0;
}

程序输出:


备注:不能使用fgets/fputs函数。因为二进制文件并没有"行"的概念。


3. 临时文件

#include <stdio.h>

#define MAXLINE 4096
int main( void )
{
        char    name[L_tmpnam], line[MAXLINE];
        FILE    *fp;
        printf("%s\n", tmpnam(NULL));
        tmpnam(name);
        printf("%s\n", name);

        if ( ( fp = tmpfile()) == NULL ){
                printf("tmpfile error\n");
                return 1;
        }
        fputs("one line of output\n", fp );
        rewind(fp);
        if ( fgets(line,sizeof(line), fp) == NULL ){
                printf("fgets error\n");
                return 1;
        }
        fputs(line, stdout);

        return 0;
}

程序输出:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值