前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >标准I/O (二).缓冲型IO库函数

标准I/O (二).缓冲型IO库函数

作者头像
franket
发布2021-09-16 09:56:40
4590
发布2021-09-16 09:56:40
举报
文章被收录于专栏:技术杂记技术杂记

前言

当前的计算系统除了包括对数据有 加工和处理 以外还有 搬运

这个 搬运 代表着 输入和输出 ,及 input/output ,简称 I/O

UNIX/Linux 的缔造者们将数据的 来源和目标 都抽象为 文件,所以在 UNIX/Linux 系统中 一切皆文件

一切皆文件 不仅仅对磁盘,还包括鼠标,键盘,显示器这些设备,那么对这些设备的操作也都抽象成了对 文件的I/O操作

关于 标准I/O 可以参看前面一篇文章 《标准I/O (一)》 ,关于C语言的API(linux)可以参看 Linux C API 参考手册 在线文档

这里分享一下我在学习 UNIX I/O 库过程中的笔记和心得


概要


标准IO库的常用函数

下面是一些 标准IO库中的常用函数

代码语言:javascript
复制
File *fopen(const char*path,const char *mode)
int fseek(FILE *stream, long offset, int whence)
long ftell(FILE *stream)
void rewind(FILE *stream)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
int fclose(FILE *stream)
void *malloc(size_t size)
void free(void *ptr)

代码示例

给定一个已知文件a(大小确定,文件内容自行用vi输入n个字符),将文件中的内容倒序后存入文件b中。路径都在/home/emacs/file/下

代码语言:javascript
复制
#include <stdio.h> //标准IO库
#include <malloc.h> //动态内存分配函数库

int slen(char *s) //求字符串长度 (string.h中的strlen函数有相同功能)
{
  int i=0;
  for(;*s!='\0';s++)i++; //使用i进行计数
  return i;
}

char * srev(char *s) //字符串翻转(因为没有现成的翻转函数,所以得自己写)
{
  int i=0,len=slen(s); 
  char tmpc='\0'; //之所以将各种变量定义后,同时进行赋值初始化,是为了避免不可知不可控的状况
  for(i=0;i<len/2;i++) //从字符串两边往中间依次进行收尾对调
  {
    tmpc=s[i];
    s[i]=s[len-1-i];
    s[len-1-i]=tmpc;
  }
  return s;
}

int main()
{
  FILE *fp=NULL,*fb=NULL;
  char *fileA="/home/emacs/file/a";
  char *fileB="/home/emacs/file/b";
  char *tmps=NULL;
  long len=0; //进行各种赋值初始化

  if(NULL == (fb=fopen(fileB,"w+"))) //以写也可读的方式打开文件B,出错则提醒并退出
  {
    printf("cannot open file:%s\n",fileB);
    return -1;
  }
  if(NULL == (fp=fopen(fileA,"r+"))) //以读也可写的方式打开文件A,出错则提醒并退出
  {
    printf("cannot open file:%s\n",fileA);
    return -1;
  }

  fseek(fp,0L,2); //定位到文件末尾
  len=ftell(fp); //取出当前的位置偏移量,是为了获取文件长度
  if(1 > len) //如果文件为空,就提醒并退出					    
  {
    printf("%s is a empty file,please input something\n",fileA);
    return -1;
  }
  rewind(fp); //重新归置文件指针位置到文件开头
  if (NULL == (tmps=(char*)malloc(sizeof(char)*(len+1)))) //申请一段长度为len+1个char的空间,出错则提醒并退出
  {
    printf("no enough memory\n");
    return -1;	
  } 
  if(1 != fread(tmps,sizeof(char)*len,1,fp)) //从文件A中读取len个char长度的内容写到tmps的临时空间中,出错则提醒并退出
  {
    printf("file read error:%s\n",fileA);
    return -1;
  }  
  tmps[len]='\0'; //将结尾加上字符串结束符,之所以进行这一步,是为了给翻转作准备的,没有'\0'结尾,很可能产生乱码
  srev(tmps); //将字符串内容进行翻转
  if(1 != fwrite(tmps,sizeof(char)*len,1,fb))  //从tmps的临时空间中读取len个char长度的内容写到文件B中,出错则提醒并退出
  {
    printf("file write error:%s\n",fileB);
    return -1;
  }
  free(tmps); //释放tmps的临时空间
  fclose(fp); //关闭文件A
  fclose(fb); //关闭文件B,这步操作可以有效避免缓存未刷新到硬盘的潜在隐患
  return 0;
}

Note: 文件打开数是一种系统资源,是有上限的,虽然程序退出后,系统会帮忙清理,但在程序设计中,打开文件,使用完后进行手动关闭是一种很好的习惯,这样可以有效避免缓存未刷新的潜在隐患

编译执行

代码语言:javascript
复制
emacs@ubuntu:~/c$ alias gtc
alias gtc='gcc -Wall -g -o'
emacs@ubuntu:~/c$ gtc acopytob.x acopytob.c 
emacs@ubuntu:~/c$ cat /home/emacs/file/a
1234567890abcdef
emacs@ubuntu:~/c$ cat /home/emacs/file/b
emacs@ubuntu:~/c$ ./acopytob.x 
emacs@ubuntu:~/c$ cat /home/emacs/file/a
1234567890abcdef
emacs@ubuntu:~/c$ cat /home/emacs/file/b

fedcba0987654321emacs@ubuntu:~/c$ 
emacs@ubuntu:~/c$

编译执行过程中没有报错,从结果来看,b文件中的内容变化也符合预期


总结

以下这些函数可以应对绝大部分的IO需求

  • fopen/fclose
  • fread/fwrite
  • fseek/ftell/rewind

通过各方面资料弄懂其参数的意义和返回值的类型,是熟练掌握的基础

原文地址

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 概要
    • 标准IO库的常用函数
      • 代码示例
        • 编译执行
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档