1.fopen

表头文件

include

定义函数

FILE * fopen(const char * path,const char * mode);

函数说明

参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。

mode有下列几种形态字符串:

r 打开只读文件,该文件必须存在。

r+ 打开可读写的文件,该文件必须存在。

w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。

w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。

a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。

a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。

上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b 字符用来告诉函数库打开的文件为二进制文件,而非纯文字文件。不过在POSIX系统,包含Linux都会忽略该字符。由fopen()所建立的新文件会具有S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)权限,此文件权限也会参考umask值。

返回值

文件顺利打开后,指向该流的文件指针就会被返回。若果文件打开失败则返回NULL,并把错误代码存在errno 中。

注意:

一般而言,开文件后会作一些文件读取或写入的动作,若开文件失败,接下来的读写动作也无法顺利进行,所以在fopen()后请作错误判断及处理。

2.fread函数和fwrite函数

1.函数功能

用来读写一个数据块。

2.一般调用形式

fread(buffer,size,count,fp);

fwrite(buffer,size,count,fp);

3.说明

(1)buffer:是一个指针,对fread来说,它是读入数据的存放地址。对fwrite来说,是要输出数据的地址。

(2)size:要读写的字节数;

(3)count:要进行读写多少个size字节的数据项;

(4)fp:文件型指针。

注意:1 完成一次写操(fwrite())作后必须关闭流(fclose()),因为fwrite写数据后,数据只是到了缓冲区,而没有真正的写在了文件里,等fclose执行后,fclose函数隐含包含了一次fflush操作,把缓冲区内的数据冲洗到终端;

2 完成一次读操作(fread())后,如果没有关闭流(fclose()),则指针(FILE * fp)自动向后移动前一次读写的长度,不关闭流继续下一次读操作则接着上次的输出继续输出;fread()用来从文件流中读取数据。参数fp为已打开的文件指针,参数ptr 指向欲存放读取进来的数据空间,读取的字符数以参数size*nmemb来决定。Fread()会返回实际读取到的nmemb数目,如果此值比参数nmemb 来得小,则代表可能读到了文件尾或有错误发生,这时必须用feof()或ferror()来决定发生什么情况。

fwrite()用来将数据写入文件流中。参数fp为已打开的文件指针,参数buffer指向欲写入的数据地址,总共写入的字符数以参数size*nmemb来决定。Fwrite()会返回实际写入的nmemb数目。

3 fprintf() :

#include

int fprintf( FILE *stream, const char *format, ... );

函数功能:把格式化的数据写入某个字符串

函数原型:int sprintf( char *buffer, const char *format [, argument] … );

返回值:字符串长度(strlen)

char name[20] = "Mary";

FILE *out;

out = fopen( "output.txt", "w" );

if( out != NULL )

fprintf( out, "Hello %s\n", name );

格式化规定符

%d 十进制有符号整数

%u 十进制无符号整数

%f 浮点数

%s 字符串

%c 单个字符

%p 指针的值

%e 指数形式的浮点数

%x, %X 无符号以十六进制表示的整数

%0 无符号以八进制表示的整数

%g 自动选择合适的表示法

按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, ...]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了。注意的是返回值为此次操作写入到文件的字节数。如int c = fprintf(fp, "%s %s %d %f", str1,str2, a, b) ;str1:10字节;str2: 10字节;a:2字节;b:8字节,c为33,因为写入时不同的数据间自动加入一个空格。

4.fclose

函数原型:int fclose(FILE *stream)

功能:关闭一个文件流,使用fclose就可以把缓冲区内最后剩余的数据输出到磁盘文件中,并释放文件指针和有关的缓冲区

返回值

若关文件动作成功则返回0,有错误发生时则返回EOF并把错误代码存到errno。

fopen /open区别

UNIX环境下的C 对二进制流文件的读写有两套班子:1) fopen,fread,fwrite ; 2) open, read, write

这里简单的介绍一下他们的区别。

fopen 系列是标准的C库函数;open系列是 POSIX 定义的,是UNIX系统里的system call。

也就是说,fopen系列更具有可移植性;而open系列只能用在 POSIX 的操作系统上。

使用fopen 系列函数时要定义一个指代文件的对象,被称为“文件句柄”(file handler),是一个结构体;而open系列使用的是一个被称为“文件描述符” (file descriptor)的int型整数。

fopen 系列是级别较高的I/O,读写时使用缓冲;而open系列相对低层,更接近操作系统,读写时没有缓冲。由于能更多地与操作系统打交道,open系列可以访问更改一些fopen系列无法访问的信息,如查看文件的读写权限。这些额外的功能通常因系统而异。

使用fopen系列函数需要"#include ";使用open系列函数需要"#include " ,链接时要之用libc(-lc)

小结:

总的来说,为了使程序获得更好的可移植性,未到非得使用一些fopen系列无法实现的功能的情况下,fopen系列是首选。

read/write和fread/fwrite区别

1,fread是带缓冲的,read不带缓冲.

2,fopen是标准c里定义的,open是POSIX中定义的.

3,fread可以读一个结构.read在linux/unix中读二进制与普通文件没有区别.

4,fopen不能指定要创建文件的权限.open可以指定权限.

5,fopen返回指针,open返回文件描述符(整数).

6,linux/unix中任何设备都是文件,都可以用open,read.

如果文件的大小是8k。

你如果用read/write,且只分配了2k的缓存,则要将此文件读出需要做4次系统调用来实际从磁盘上读出。

如果你用fread/fwrite,则系统自动分配缓存,则读出此文件只要一次系统调用从磁盘上读出。

也就是用read/write要读4次磁盘,而用fread/fwrite则只要读1次磁盘。效率比read/write要高4倍。

如果程序对内存有限制,则用read/write比较好。

都用fread 和fwrite,它自动分配缓存,速度会很快,比自己来做要简单。如果要处理一些特殊的描述符,用read 和write,如套接口,管道之类的

系统调用write的效率取决于你buf的大小和你要写入的总数量,如果buf太小,你进入内核空间的次数大增,效率就低下。而fwrite会替你做缓存,减少了实际出现的系统调用,所以效率比较高。

如果只调用一次(可能吗?),这俩差不多,严格来说write要快一点点(因为实际上fwrite最后还是用了write做真正的写入文件系统工作),但是这其中的差别无所谓。

fclose与close的区别

C FILE *流在内部使用缓冲I / O. fclose()刷新此缓冲区,然后在OS级别关闭文件描述符。close()'FILE *流可能无法刷新此内部缓冲区,您可能会丢失数据。因此对于C流总是使用C fxxx()函数

fclose函数隐含包含了一次fflush操作,把缓冲区内的数据冲洗到终端(因为标准I/O的操作对文件有缓冲,所以需要刷新缓冲区,close没有这个操作,也没有必要刷新的操作,因为对应的open,write,read没有缓冲)

在标准IO中,对于文件的读写无非三种方式:

(1) 每次一个字符的I / O。

(2) 每次一行的I / O。

(3) 直接I / O。

似乎这些函数看起来很简单,但只有理解了这些函数,你才知道该如何使用,例如怎样来判断读取的文件是否结束,怎样来统计文件的行数,等等。

下面先来回顾下读取文件的三种方式,然后再举例看下怎样使用。

一次读或写一个字符,使用getc、fgetc或getchar。如果流是带缓存的,则标准I / O函数处理所有缓存。三个函数原型如下:

#include

int getc(FILE *fp) ;

int fgetc(FILE *fp) ;

int getchar(void);

三个函数的返回:若成功则为下一个字符,若已处文件尾端或出错则为EOF。强调的是不管是出错还是到达文件尾端,这三个函数都返回同样的值。为了区分这两种不同的情况,必须调用ferror()或feof()。

一次读或写一行,使用fgets和gets。两个函数原型如下:

#include

Char *gets(char *s) ;

Char *fgets(char *s,int size,FILE *steam)

两个函数返回:若成功则为buf,若已处文件尾端或出错则为null。这两个函数都指定了缓存地址,读入的行将送入其中。gets()从标准输入读,而fgets()则从指定的流读。

对于fgets(),必须指定缓存的长度为n。此函数一直读到下一个新行符为止,但是不超过n-1个字符,读入的字符被送入缓存,该缓存以null字符结尾。如若该行,包括后一个新行符的字符数超过n-1,则只返回一个不完整的行,而且缓存总是以null字符结尾。对fgets()的下一次调用会继续读该行。

直接I / O使用的是fread。每次I / O操作读某种数量的对象,而每个对象具有指定的长度。这个函数常用于从二进制文件中读一个结构。原型如下:

int fread(void * ptr,int objsize,int objnum,FILE *fp);

这个函数返回:读的对象数。fputs()在遇到null字节时就停止,而在结构中可能含有null字节,所以不能使用每次一行函数实现这种要求,而fread能使我们一次读整个结构。

下面看下如何利用上面提到的标准IO读函数来判断你读取的文件是否结束以及如何来统计文件的行数。

1、判断文件结束有三种方式:

a) 当用fgetc(src)返回的int值为EOF时,读到文件的末尾

b) 当用fgets(p,1024,src)返回的指针为NULL时,读到文件的末尾

c) 当用fread(s,1,20,src)返回的个数小于20时,读到文件的末尾

实现起来简单明了,就不再细说。

2、统计文件的行数

a) 当用fgetc(src)返回的int值为’\n’时行数加一。

b) 当用fgets(p,1024,src)返回的指针不为NULL时,你的缓冲即提供的p[1024]已经读到字符,这个时候实际上有两种情况,一种你读进来的字符长度小于1024个,这个时候一行结束,行数加一,另一种比较复杂,由于受自己定义的缓冲的限制,一次只能读进来1023个,如果恰好这个时候你刚好读完一行,那p[]1022]里存放的一定’\n’,如果不是,那你的一行还一定没有结束了。

程序如下:

Int n;

A) While(fgetc(src)’\n’)

N++;

B) while(fgets(p,1024,src)!=NULL)

{

If(strlen(p)<1024||p[1022]’\n’)

N++;

}

标准I/O操作函数

1)打开文件

打开文件有3个标准函数,分别为fopen()、fdopen()和freopen()。它们可以不同的模式打开,但都返回一个指向FILE的指针,该指针指向对应的I/O流。此后,对文件的读写都是通过这个FILE指针来进行的。其中,fopen()函数可以指定打开文件的路径和模式,fdopen()函数可以指定打开的文件描述符和模式,而freopen()函数除可指定打开的文件、模式外,还可指定特定的I/O流。

fopen()函数语法要点

其中,mode类似于open()函数中的flag,可以定义打开文件的访问权限等,表2.17说明了fopen()中mode的各种取值。

mode取值说明

注意:在每个选项中加入b字符用来告诉函数库打开的文件为二进制文件,而非纯文本文件。不过在Linux系统中会自动识别不同类型的文件而将此符号忽略。

fdopen()函数语法要点

freopen()函数语法要点

2)关闭文件

关闭标准流文件的函数为fclose(),该函数将缓冲区内的数据全部写入到文件中,并释放系统所提供的文件资源。

fclose()函数语法要点

3)读文件

在文件流被打开后,可对文件流进行读写等操作,其中,读操作的函数为fread()。

fread()函数语法要点

4)写文件

fwrite()函数用于对指定的文件流进行写操作。

fwrite()函数语法要点

文件打开之后,根据一次读写文件中字符的数目可分为字符输入/输出、行输入/输出和格式化输入/输出,下面分别对这3种不同的方式进行讨论。

1)字符输入/输出

字符输入/输出函数一次仅读写一个字符。其中字符输入/输出函数的语法如下表所示:

字符输入函数语法

字符输出函数语法

这几个函数功能类似,其区别仅在于getc()和putc()通常被实现为宏,而fgetc()和fputc()不能实现为宏,因此,函数的实现时间会有所差别。

下面这个实例结合fputc()和fgetc(),将标准输入复制到标准输出中。

/*fput.c*/

#include

main()

{

int c;

/* 把fgetc()的结果作为fputc()的输入 */

fputc(fgetc(stdin), stdout);

}

输出结果:

$ ./fput

w(用户输入)

w(屏幕输出)

2)行输入/输出

行输入/输出函数一次操作一行,其中行输入/输出函数语法要点如下表所示:

行输入函数语法

行输出函数语法

这里以gets()和puts()为例进行说明,本实例将标准输入复制到标准输出中,如下所示:

/*gets.c*/

#include

main()

{

char s[80];

fputs(fgets(s, 80, stdin), stdout);

}

运行该程序,结果如下所示:

$ ./gets

This is stdin(用户输入)

This is stdin(屏幕输出)

3)格式化输入/输出

格式化输入/输出函数可以指定输入/输出的具体格式,这里有读者已经非常熟悉的printf()、scanf()等函数,这里简要介绍一下它们的格式,如下表所示:

格式化输出函数1

格式化输出函数2

格式化输入函数

linux中流设备_Linux中的标准文件I/O流相关推荐

  1. linux中流设备_Linux IO请求处理流程 (2) — 蓄流和泄流

    说明 在请求处理流程(1)中我们分析了每个IO请求是如何从文件系统发出并进入到块设备层,加入到块设备调度队列中,在这里我们将仔细阐述每个IO请求如何从块设备的请求队列被下发至更底层处理. 数据结构 与 ...

  2. linux中流设备_Linux设备驱动子系统终极弹

    0. 预备理论 1. USB Core 2. USB Hub 3. USB OTG 4. USB Host 5. USB Gadget 6. USB Mass Storage USB博大精深,不是一两 ...

  3. linux中流设备_Linux纯干货知识总结|面试专用

    简介:学习Linux的重要性相信不用我多说大家也明白,下面小编总结了常用的Linux基础知识以及面试常问的Linux命令,建议大家装个Linux系统多练习,这样才会提升地更快! 学习Linux的重要性 ...

  4. linux中流设备_Linux USB的那些事之设备驱动子系统终极篇

    原标题:Linux USB的那些事之设备驱动子系统终极篇 USB博大精深不是一篇文章就能够解释清楚的.想要深入研究USB的话,USB协议(外加Host和OTG协议)是必要的知识,另外,国内有本< ...

  5. linux中流设备_LINUX块设备驱动1

    第1章 +---------------------------------------------------+ |                 写一个块设备驱动                 ...

  6. linux中流设备_[快速上手Linux设备驱动]之块设备驱动流程详解一

    [快速上手Linux设备驱动]之块设备驱动流程详解一 walfred已经在[快速上手Linux设备驱动]之我看字符设备驱动一 文中详细讲解了linux下字符设备驱动,并紧接着用四篇文章描述了Linux ...

  7. Linux字符设备驱动中container_of宏的作用

    Linux字符设备驱动中container_of宏的作用 首先看看这个宏的原型: container_of(ptr,type,member) 功能:根据一个结构体变量中的一个成员变量的指针来获取指向整 ...

  8. linux挂载硬盘_Linux中如何对硬盘进行分区、格式化、挂载使用

    通过VMware演示如何对硬盘进行分区.格式化.挂载使用 大家平时可能大多数使用Windows系统,对于挂载硬件设备可能很少有人了解其中的原理. 例如:平时使用u盘直接插入电脑,大家有没有考虑过Win ...

  9. linux交换内存_Linux中的交换内存如何工作?

    linux交换内存 To understand what Swap memory in Linux is, we will have a look at the concept of RAM and ...

最新文章

  1. RDKit | 可视化分子来自于xyz文件
  2. 关于css的text-indent首行缩进两个字符和图片缩进的问题
  3. postgres 支持的线程数_线程池被打满了怎么处理呢,你是否真的了解线程池?
  4. List与Set接口的方法
  5. des加密出的字符串有特殊字符吗_纯干货分享丨内网渗透很难学吗?
  6. 21天Jmeter打卡Day19 mysql数据库提取参数化
  7. 易到高管被原百度外卖CEO巩振兵逼下跪:职场人到中年的无奈
  8. dataframe在最后新增一行_【TOOLS】python中对Excel进行写入操作,写入一列或者一行(openpyxl)...
  9. WinRAR压缩加密
  10. java field.gettype,Java Field getType()用法及代码示例
  11. 自研返利网源码、有需要的私信
  12. git小乌龟的安装和使用教程
  13. 支付宝手机网站支付接口集成的经验小结
  14. 自动控制理论开环与闭环思考(从飞行控制角度)
  15. BMP与PPM格式的转换
  16. 唯一历经五朝的皇妃,其印鉴藏于天津博物馆
  17. LOGO创意-IT行业-随记
  18. c# WPF 动态设置button的IsEnabled属性
  19. 【啃书】【阿里云天池大赛赛题解析】目录
  20. 聊聊华为校招流程及安排——23届实习、提前批、正式批(数字IC、FPGA逻辑、通信、软件等)

热门文章

  1. Java 设计模式之Mediator调节者模式
  2. 使用Spring Boot Actuator 监控程序运行状态
  3. Java 算法 超级玛丽
  4. 中移4G模块-ML302-OpenCpu开发-GPIO
  5. 关于人行acs对账不及时_记工记账新方法,不用本子不用笔,一个手机全搞定
  6. python使用virtualenv在本地新建虚拟环境
  7. 解决file.seek()读取文件报错:AttributeError: ‘str‘ object has no attribute ‘seek‘
  8. java异常处理 ppt_Java异常处理、多线程ppt课件
  9. 比特币可视化工具_这个比特币交易“可视化”网站,用一辆公交车带你“上车”...
  10. php jq表格,如何用jQuery操作表单和表格