系统IO跟标准IO的联系与区别

一、         什么是系统IO和标准IO

系统IO:系统IO又称文件IO,也称低级磁盘IO,属于不带缓存的IO(unbuffered I/O)。也就是一般所说的低级I/O——操作系统提供的基本IO服务,与OS绑定,特定于Linux或unix平台。

标准IO:标准IO被称为高级磁盘IO,标准IO提供三种类型的缓存:

u 全缓存:当填满标准IO缓存后才进行实际的IO操作

u 行缓存:当输入或输出中遇到新行符时,标准IO库执行IO操作

u 不带缓存:例如stderr

设置缓冲类型函数:int setvbuf(FILE *stream,char *buf,int type,unsignedsize)

Ø  stream:指向流的指针

Ø  buf:期待缓冲区的地址

Ø  type:期待缓冲区的类型

Ø  size:缓冲区内字节的数量

type有以下值

Ø  _IOFBF(满缓冲):当缓冲区为空时,从流读入数据。或者当缓冲区满时,向流写入数据

Ø  _IOLBF(行缓冲):每次从流中读入一行数据或向流中写入一行数据

Ø  _IONBF(无缓冲):直接从流中读入数据或直接向流中写入数据,而没有缓冲区

二、文件IO跟标准IO的区别

1、  通过系统IO读写文件时,每次操作都会执行相关系统调用。这样处理的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销。标准IO可以看成是在文件IO的基础上封装了缓冲机制。先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数。

2、  文件IO中用文件描述符表现一个打开的文件,可以访问不同类型的文件,如普通文件、设备文件和管道文件等。而标准IO中用FILE(流)表示一个打开的文件,通常只用来访问普通文件。

三、文件IO跟标准IO的函数

1、 打开文件:fopen与open

1)      标准IO使用fopen打开文件:FILE *fp= fopen(const char* path,const char* mode);其中path是文件名mode用于指定文件打开的模式的字符串如果成功打开,返回一个FILE文件指针,如果失败返回NULL。这里的文件指针并不是指向实际的文件,而是一个关于文件信息的数据包,其中包括文件使用的缓存信息。

 

mode的字符串形态:

Ø  r以只读方式打开文件,该文件必须存在

Ø  r+:以读/写方式打开文件,该文件必须存在

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

Ø  w+:打开可读/可写文件,若文件存在则文件长度清0,即该文件内容消失,若文件不存在则创建该文件

Ø  a:以附加的方式打开只写文件。若文件不存在,则会创建该文件,若文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符保留)

Ø  a+:以附加的方式打开可读/可写文件。若文件不存在,则会创建该文件,若文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符不保留)

上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b字符用来告诉函数库以二进制模式打开文件。如果不加b,表示默认加了t,即rt、wt,其中t表示以文本模式打开文件。如:

Ø  rb+:以读/写方式打开一个二进制文件,只允许读/写数据

Ø  rt+:以读/写方式打开一个文本文件,允许读和写

Ø  wb:以只写方式打开或新建一个二进制文件,只允许写数据

Ø  wb+:以读/写方式打开或新建一个二进制文件,允许读和写

Ø  wt+:以读/写方式打开或新建一个文本文件,允许读写

Ø  ab+:以读/写方式打开一个二进制文件,允许读或在文件末尾追加数据

Ø  at+;以读/写方式打开一个文本文件,允许读或在文件末尾追加数据

EOF符:表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放,而ASCII代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。实际上EOF的值通常为-1,但他依系统有所不同。很多文件处理函数错误后的返回值也是EOF,因此常被用来判断调用一个函数是否成功

  

2)      系统IO使用open函数打开一个文件:int fd =open(char *name,int type);与fopen类似,name表示文件名字符串,而type指定打开的模式成功返回一个正整数成为文件描述符,这与标准IO显著不同,失败的话返回-1,与标准IO返回NULL也是不同的。

type的形态

Ø  O_RDONLY(只读)

Ø  O_WRONLY(只写)

Ø  O_RDWR(可读可写)

2、 关闭文件:fclose和close

打开文件与关闭文件一般成对存在,这样做的目的是为了防止没有关闭文件而造成数据流失

1)      标准IO使用fclose关闭文件,与打开文件是相对的。将文件指针传入即可,如果成功关闭,返回0,否则返回EOF

2)      系统IO使用close关闭文件,与fclose类似,只不过当错误发生时返回的是-1,而不是EOF,成功关闭同样是返回0

3、 读文件:getc,fgetc,gets,fgets,fscanf,getchar,fread和read

1)      标准IO读取文件

u  getc:一个字符一个字符读取。该函数原型为intgetc(FILE *stream),从指定FILE对象的指针stream获取下一个字符,并把位置标识符往前移动

u  fgetc:该函数的返回值,是返回所读取的一个字节。一般形式如下:ch = fgetc(fp);该函数的作用是从指定的文件(fp指向的文件)上读入一个字符赋给ch,需要注意的是,该文件必须是以读或者写的读写的方式打开,当函数读取出错或者遇到文件结束符时,将返回一个文件结束标志EOF

u  gets:接受一个文件指针的参数,不判断目标数组是否能够容纳读入的字符,可能导致溢出,不建议使用

u  fgets:以字符串单位进行读取,读到遇到的第一个换行字符的后面。

函数原型:char* fgets(char*s,int size,FILE *stream)

Ø  s:用于存储输入的地址,跟gets一样

Ø  size:表示输入字符串的最大长度,为整数

Ø  stream:指向要读取的文件的文件指针

u  fscanf:从一个流中执行格式化输入,fscanf遇到空格和换行符时结束,注意的空格也结束,这与fgets有区别,fgets遇到空格不结束。成功返回读入的参数的个数,失败返回EOF(-1)。fscanf与scanf类似,只不过增加了一个参数用于指定操作的文件,比如fscanf(fp,”%s,%s”,&arr,&ch)

函数原型:intfscanf(FILE *stream,char *format,[argument..])

Ø  stream:文件指针

Ø  format:格式化字符串

Ø  argument:输入列表

u  getchar:在输入缓冲区顺序读入一个字符(包括空格、回车和Tab)

Ø  使用while(getchar() != ‘\n’);清除回车

Ø  getche()getch()代替getchar(),其作用是从键盘读入一个字符(不用按回车),注意要包含头文件<conio.h>

u  fread:从文件流中读取数据,最多读取count个项,每个项size个字节。如果调用成功返回实际读取到的项个数(小于或等于count),如果不成功或读到文件末尾返回0

函数原型:ssize_tfread(void *buffer,size_t size,size_t count,FILE *stream)

Ø  buffer:用于接收数据的内存地址

Ø  size:要读取的每个数据项的字节数,单位是字节

Ø  count:要读count个数据项,每个数据项size个字节

Ø  stream:输入流

2)      系统IO读取文件

u  read:把参数fd所指的文件传送nbyte个字节到buf指针所指的内存中。若参数nbyte为0,则read()不会有作用并返回0。返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或无可读取的数据。错误返回-1,并将根据不同的错误原因适当的设置错误码。

函数原型:ssize_tread(int fd,void *buf,size_t count)

Ø  fd:文件描述符

Ø  buf:读出数据的缓冲区

Ø  count:每次读取的字节数

4、 写文件:putc,fputc,puts,fputs,putchar,fprintf,fwrite和write

1)      标准IO写文件

u  putc:原型为int fputc(),也就是说putc()等价于fputc()。不同的是,putc函数被定义为宏时,它可能多次计算stream的值

u  fputc:fp所指向的文件的当前读写位置写入一个字符。写入字符成功则函数返回值为该字符的ASCII值,写入字符不成功则返回值为EOF。当正确写入一个字符或一个字节的数据后,文件内部写指针会自动后移一个字节的位置。虽然函数被定于为整形数,但仅用其低八位。

                   函数原型:int fputc(int ch,FILE*fp)

Ø  ch:要写入的字符

Ø  fp:文件描述符

u  puts:用来向标准输出设备(屏幕)输出字符串并换行。具体为:把字符串输出到标准输出设备,将’\0’转换为回车换行。其调用方式为,puts(s);其中s为字符串字符(字符串数组名或字符串指针)

                   函数原型:intputs(const char* string)

Ø  string:要输出的字符串

²  puts()函数只能输出字符串,不能输出数值或进行格式变换。

²  可以将字符串直接写入puts()函数中,如puts(“hello world”)

²  putsprintf的用法一样,puts()函数的作用与语句”printf(“%s\n”,s)”的作用相同。注意:puts在输出字符串后会自动输出一个回车符

u  fputs:向指定的文件写入一个字符串(不自动写入字符串结束标记符’\0’)。成功写入一个字符串后,文件的位置指针会自动后移,函数返回值为非负数,否则返回EOF(符号常量,其值为-1)

函数原型:intfputs(const char* str,FILE *stream)

Ø  str:这是一个数组,包含了要写入的以空字符串终止的字符序列

Ø  stream:指向FILE对象的指针,该FILE对象标识了要被写入字符串的流

u  putchar:将指定的表达式的值所对应的字符输出到标准输出终端上,表达式可以是字符型或整形。每次只能输出一个字符。当输出正确时,返回输出字符转换为的unsigned int值,当输出错误时,返回EOF文件结束符。

putchar函数的基本格式为:putchar(c)

Ø  c为一个被单引号(英文状态下)引出来的字符时,输出该字符(注:该字符也可以为转义字符)

Ø  c为一个介于0~127(包括0127)之间的10进制整型数时,它会被视为对应字符的ASCII码,输出该ASCII码对应的字符

Ø  c为一个事先用char定义好的字符型变量时,输出该变量所指向的字符

u  fprintf:格式化输出到一个流/文件中,fprintf函数根据指定的格式(format)向输出流(stream)写入数据(argument)。fprintf()会根据参数format字符串来转换并格式化数据,然后将结果输出到参数stream指定的文件中,直到出现字符串结束符(‘\0’)为止。fprintf()的返回值是输出的字符数,发生错误时返回一个负值。

函数原型:intfpintf(FILE *stream,const char* format,[argument..])

Ø  stream:文件指针

Ø  format:输出格式

Ø  [argument]:附加参数列表

format格式:

%d:十进制有符号整数

%u:十进制无符号整数

%f:浮点数

%s:字符串

%c:单个字符

%p:指针的值

%e:指针形式的浮点数

%x/%X:十六进制有/无符号整数

%o:八进制无符号整数

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

u  fwrite:向指定的文件中写入若干数据块,如成功执行则返回实际写入的数据块数目。该函数以二进制形式对文件进行操作,不局限与文本文件。返回实际写入的数据块数目

函数原型:size_tfwrite(const void* buffer,size_t size,size_t count,FILE* stream)

Ø  buffer:要获取数据的地址

Ø  size:要写入内容的单字节数

Ø  count:要进行写入size字节的数据项的个数

Ø  stream:目标文件指针

2)      系统IO写文件

u  write:把指针buf所指的内存写入count个字节到参数fd所指的文件内,文件读写位置也会随之移动。如果顺利写入则会返回实际写入的字节数,当有错误发生时则返回-1,错误码存入errno中。

函数原型:ssize_twrite(int fd,void *buf,size_t count)

Ø  fd:文件描述符

Ø  buf:指定的缓冲区

Ø  count:要写入文件指定的字节数

可能出现的错误码:

Ø  EINTR:此调用被信号中断

Ø  EAGAIN:当使用不可阻断I/O时(O_NONBLOCK),若无数据可读取则返回此值

Ø  EBADF:参数fd非有效的文件描述符,或该文件以关闭

5、 随机存取:fssek,ftell和lseek

1)      标准IO随机存取

u  fseek:重定位流(数据流/文件)上的文件内部位置指针。如果执行成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置。函数返回0。如果执行失败(比如offset取值大于等于2*1024*1024*1024,即long的正数范围2G),则不改变stream指向的位置,函数返回一个非0值。

                   函数原型:int fseek(FILE*stream,long offset,int fromwhere)

Ø  stream:文件指针

Ø  offset:偏移量大小,正数表示正向偏移,负数表示负向偏移

Ø  fromwhere:偏移模式

          偏移模式:   0——SEEK_SET(文件开头)

1——SEEK_CUR(当前位置)

                                    2——SEEK_END(文件结尾)

          如:fseek(fp,100L,SEEK_SET)把stream指针移动到离文件头100个字节处

                   fseek(fp,100L,SEEK_CUR)把stream指针移动到离当前位置100个字节处

                   fseek(fp,-100L,SEEK_END)把stream指针移动到离文件尾100个字节处     

u  ftell:用于得到文件位置指针当前位置相对于文件首的偏移字节数。在随机方式存取文件时,由于文件位置频繁的前后移动,程序不容易确定文件的当前位置。使用fseek函数后再调用ftell函数就可以非常容易地确定文件的当前位置。因为ftell返回long型,根据long型的取值范围-231~231-1-21474836482147483647),故对大于2.1G的文件进行操作时出错

                   函数原型:long ftell(FILE *stream)

Ø  stream:文件指针

利用函数ftell()也能方便地知道一个文件的大小。如以下语句序列:

                   fseek(fp,0L,SEEK_END);

                   int len = ftell(fp);

首先将文件的当前位置移动文件的末尾,然后调用函数ftell()获得当前位置相对于文件首的位移,该位移值等于文件所含字节数

2)      系统IO随机存取

u  lseek:使用UNIX系统调用来读取文件内容时,系统究竟是从文件的哪一个位置读取数据,完全由文件指针决定。刚开始读取数据时,文件指针通常是指向文件的起始位置。当调用函数成功时则返回目前的读写位置,也就是距离文件开头多少个字节。若有错误则返回-1,errno会存放错误码。Linux系统不允许lseek()tty装置作用,此项动作会令lseek()返回ESPIPE

可能设置errno的错误代码:

Ø  EBADFfildes不是一个打开的文件描述符

Ø  ESPIPE:文件描述符被分配到一个管道、套管字或FIFO

Ø  EINVALwhence取值不当

函数原型:off_t lseek(int fildes,off_t offset,intwhence)

Ø  fildes:文件描述符

Ø  offset:偏移量大小

Ø  whence:偏移模式       

          偏移模式:   0——SEEK_SET(文件开头)

1——SEEK_CUR(当前位置)

                                    2——SEEK_END(文件结尾)

Ø  欲将读写位置移动到文件开头时:

lseek(int fildes,0L,SEEK_SET)

Ø  欲将读写位置移动到文件尾时:

lseek(intfildes,0L,SEEK_END)

Ø  想要取得文件当前位置时:

lseek(intfildes,0L,SEEK_CUR)

                  利用lseek()函数获取文件大小,如以下语句序列:

                                   int filelen =lseek(fd,0L,SEEK_END);

                                   lseek(fd,0L,SEEK_SET);

                                   printf(“file size is%d \n”,filelen);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值