标准I/O库之标准I/O效率、二进制I/O和定位流

标准I/O的效率

使用getcputc函数将标准输入复制到标准输出。

#include "../../include/apue.h"
int main(void)
{
    int c;
    while((c=getc(stdin)) != EOF)
        if(putc(c,stdout) == EOF)
            err_sys("output error");
    if(ferror(stdin))
        err_sys("input error");
    exit(0);
}

结果如下:
在这里插入图片描述
使用fgetcfputc改写上面函数如下:

#include "../../include/apue.h"
int main(void)
{
    int c;
    while((c=fgetc(stdin)) != EOF)
        if(fputc(c, stdout) == EOF)
            err_sys("output error");
    if(ferror(stdin))
        err_sys("input error");
    exit(0);
}

结果如下:
在这里插入图片描述
使用fgetsfputs函数来实现读写行。

#include "../../include/apue.h"
int main(void)
{
    char buf[MAXLINE];
    while(fgets(buf, MAXLINE, stdin) != NULL)
        if(fputs(buf, stdout) == EOF)
            err_sys("output error");
    if(ferror(stdin))
        err_sys("input error");
    exit(0);
}

结果如下:
在这里插入图片描述

标准I/O库函数的调用与系统调用readwrite相比并不慢很多,对于大多数比较复杂的应用程序而言,最主要的用户CPU时间是由应用本身的各种处理消耗的,而不是由标准I/O例程消耗的。

二进制I/O

以下两个函数来实现二进制I/O操作。

#include <stdio.h>
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);
两个函数返回值:读或写的对象数。

测试示例(读或写数组元素):

#include "../../include/apue.h"                                                 
int main(void)                                                                  
{                                                                               
     FILE *fp;                                                                   
     if((fp=fopen("fopenfile", "w+")) == NULL){                                  
         perror("fopen error.");                                                 
         exit(1);                                                                
     }                                                                           
     float data[10] = {0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9};          
     if(fwrite(&data[2], sizeof(float), 4, fp) != 4)                             
         err_sys("fwrite error");                                                
     rewind(fp);                                                                 
     float buf[4] = {0};                                                         
     fread(buf, sizeof(float), 4, fp);                                           
     for(int i = 0; i < 4; i++)                                                  
         printf("%.1f\n", buf[i]);                                                   
     exit(0);                                                                    
}      

结果如下:
在这里插入图片描述

注意fwrite函数写入文件中的数据会出现乱码,无法直接查看。

扫描二维码关注公众号,回复: 9294838 查看本文章

测试示例(读或写结构体):

typedef struct {                                                                
    short count;                                                                
    long total;                                                                 
    char name[NAMESIZE];                                                        
}item;                                                                          
void test2()                                                                    
{                                                                               
     FILE *fp;                                                                   
     if((fp=fopen("fopenfile2","w+")) == NULL)                                   
         perror("fopen error");                                                  
     item i = {12, 255, "dunkwan"};                                              
     if(fwrite(&i, sizeof(item), 1, fp) != 1)                                    
     {                                                                           
         err_sys("fwrite error");                                                
     }                                                                           
     rewind(fp);                                                                 
     item j;                                                                     
     memset(&j, 0, sizeof(item));                                                
     fread(&j, sizeof(item), 1, fp);                                             
     printf("%d %ld %s\n", j.count, j.total, j.name);                            
}

结果如下:
在这里插入图片描述

使用二进制I/O的基本问题是,它们只能用于读在同一系统上已写的数据。

定位流

三种定位标准I/O的方法。

ftellfseek函数

#include <stdio.h>
long ftell(FILE *fp);
返回值: 若成功,返回文件当前位置;若出错,返回 -1Lint fseek(FILE *fp, long offset, int whence);
返回值:若成功,返回0; 若出错,返回 -1void rewind(FILE *fp);

fseekoffset参数表示偏移量,whence参数来指定在当前流中的位置,其值可为与lseek中相同的三个值,分别是SEEK_SET(表示文件起始位置)、SEEK_CUR(表示文件当前位置)以及SEEK_END(表示文件末尾位置)。rewind函数用于将流当前位置设为文件的起始位置。

ftellofseeko函数

#include <stdio.h>
off_t ftello(FILE *fp);
返回值: 若成功,返回文件当前位置;若出错,返回(off_t)-1int fseeko(FILE *fp, off_t offset, int whence);
返回值: 若成功,返回 0;若错误,返回 -1

ftelloftell除了off_tlong不同外,其他相同。fseekofseek也是如此。

fgetposfsetpos函数

#include <stdio.h>
int fgetpos(FILE *restrict fp, fpos_t *restrict pos);
int fsetpos(FILE *fp, const fpos_t *pos);
两个函数返回值:若成功, 返回0;若出错,返回非0

测试示例:

 #include "../../include/apue.h"                                                 
 void test()                                                                     
 {                                                                               
      FILE *fp;                                                                   
      if((fp=fopen("fgfsfile", "w+")) == NULL)                                    
          perror("fopen error");                                                  
      fseek(fp, 255, SEEK_CUR);                                                   
      fpos_t *p =(fpos_t *)malloc(sizeof(fpos_t));                                
      fgetpos(fp, p);                                                             
      char buf[100] = "hello world!";
      fwrite(buf, 1, strlen(buf), fp);                                            
      fsetpos(fp, p);                                                             
      char res[100];                                                              
      memset(res, 0,sizeof(res));                                                 
      fread(res, 1, sizeof(res), fp);                                             
      printf("res = %s\n", res);                                                  
 }                                                                               
int main()                                                                      
{                                                                               
    test();                                                                     
    return 0;                                                                   
} 

结果如下:
在这里插入图片描述
由上图可知,fgetpos函数获取当前流的位置,经过fwrite函数写入数据后,再将之前获取的流位置设置为流的位置,故通过fread函数得到的数据为写入的数据

发布了229 篇原创文章 · 获赞 17 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_40073459/article/details/104384940