Linux中的标准⽂件IO流
1.fopen
表头⽂件
include<stdio.h>
定义函数
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.说明
fgets和fgetc的区别(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 <stdio.h>
int fprintf( FILE *stream, const char *format, ... );
函数功能:把格式化的数据写⼊某个字符串
函数原型:int sprintf( char *buffer, const char *format [, argument] … );
返回值:字符串长度(strlen)
char name[20] = "Mary";
FILE *out;
out = fopen( "", "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, ...]);其⽤法和prin
tf()相同,不过不是写到控制台,⽽是写到流罢了。注意的是返回值为此次操作写⼊到⽂件的字节数。如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
这⾥简单的介绍⼀下他们的区别。
1. fopen 系列是标准的C库函数;open系列是 POSIX 定义的,是UNIX系统⾥的system call。
也就是说,fopen系列更具有可移植性;⽽open系列只能⽤在 POSIX 的操作系统上。
2. 使⽤fopen 系列函数时要定义⼀个指代⽂件的对象,被称为“⽂件句柄”(file handler),是⼀个结构体;⽽open系列使⽤的是⼀个被称为“⽂件描述符” (file descriptor)的
int型整数。
3. fopen 系列是级别较⾼的I/O,读写时使⽤缓冲;⽽open系列相对低层,更接近操作系统,读写时没有缓冲。由于能更多地与操作系统打交道,open系列可以访问更改⼀些
fopen系列⽆法访问的信息,如查看⽂件的读写权限。这些额外的功能通常因系统⽽异。
4. 使⽤fopen系列函数需要"#include <sdtio.h>";使⽤open系列函数需要"#include <fcntl.h>" ,链接时要之⽤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 <stdio.h>
int getc(FILE *fp) ;
int fgetc(FILE *fp) ;
int getchar(void);
三个函数的返回:若成功则为下⼀个字符,若已处⽂件尾端或出错则为EOF。强调的是不管是出错还
是到达⽂件尾端,这三个函数都返回同样的值。为了区分这两种不同的情况,必须调⽤ferror()或feof()。
⼀次读或写⼀⾏,使⽤fgets和gets。两个函数原型如下:
#include <stdio.h>
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()函数可以指定打开⽂件的路径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<stdio.h>
main()
{
int c;
/* 把fgetc()的结果作为fputc()的输⼊ */
fputc(fgetc(stdin), stdout);
}
输出结果:
$ ./fput
w(⽤户输⼊)
w(屏幕输出)
2)⾏输⼊/输出
⾏输⼊/输出函数⼀次操作⼀⾏,其中⾏输⼊/输出函数语法要点如下表所⽰:
⾏输⼊函数语法
⾏输出函数语法
这⾥以gets()和puts()为例进⾏说明,本实例将标准输⼊复制到标准输出中,如下所⽰:
/*gets.c*/
#include<stdio.h>
main()
{
char s[80];
fputs(fgets(s, 80, stdin), stdout);
}
运⾏该程序,结果如下所⽰:
$ ./gets
This is stdin(⽤户输⼊)
This is stdin(屏幕输出)
3)格式化输⼊/输出
格式化输⼊/输出函数可以指定输⼊/输出的具体格式,这⾥有读者已经⾮常熟悉的printf()、scanf()等函数,这⾥简要介绍⼀下它们的格式,如下表所⽰:格式化输出函数1
格式化输出函数2
格式化输⼊函数
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论