文件读写IO

时间:2021-09-23 15:42:00

摘要:本文主要总结了以下有关文件读写的IO,系统调用与库函数。

1.初级IO函数:close,creat,lseek,open,write

文件描述符是一个整型数

1.1close

1.2int creat(const char * pathname, mode_t mode);

int creat(const char * pathname, mode_t mode);
函数功能:
创建一个文件并以只写的方式打开。如果原来该文件存在,会将这个文件的长度截短为0。
函数说明
若函数执行成功则返回打开文件的描述符,出错返回-1并设置errno。(关于errno详见《UNIX环境高级编程》第一章第七节)
参数pathname指向欲建立的文件路径字符串。creat()相当于使用下列的调用方式调用open()
open(const char * pathname ,(O_CREAT|O_WRONLY|O_TRUNC));
由于creat函数创建文件后是以只写的方式打开,因此局限性比较大,所以一般都用open函数来代替creat函数创建一个文件,这样创建后就能同时以读写的方式打开文件了。

1.3off_t lseek(int fildes,off_t offset ,int whence)

#include<sys/types.h>
#include<unistd.h>

定义函数

off_t lseek(int fildes,off_t offset ,int whence);

函数说明

每一个已打开的文件都有一个读写位置,当打开文件时通常其读写位置是指向文件开头,若是以附加的方式打开文件(如O_APPEND),则读写位置会指向文件尾。当read()或write()时,读写位置会随之增加,lseek()便是用来控制该文件的读写位置。参数fildes 为已打开的文件描述词,参数offset 为根据参数whence来移动读写位置的位移数。
Offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)。

参数

whence为下列其中一种:(SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2).
SEEK_SET 将读写位置指向文件头后再增加offset个位移量。
SEEK_CUR 以目前的读写位置往后增加offset个位移量。
SEEK_END 将读写位置指向文件尾后再增加offset个位移量。
当whence 值为SEEK_CUR 或SEEK_END时,参数offet允许负值的出现。
下列是较特别的使用方式:
1) 欲将读写位置移到文件开头时:
lseek(int fildes,0,SEEK_SET);
2) 欲将读写位置移到文件尾时:
lseek(int fildes,0,SEEK_END);
3) 想要取得目前文件位置时:
lseek(int fildes,0,SEEK_CUR);

返回值

当调用成功时则返回目前的读写位置,也就是距离文件开头多少个字节。若有错误则返回-1,errno 会存放错误代码

1.4int open(const char *pathname, int flags);
作用:打开和创建文件。
简述:
#include <fcntl.h>

intopen(const char *pathname, int flags, mode_t mode);
返回值:成功则返回文件描述符,否则返回 -1
对于open函数来说,第三个参数仅当创建新文件时(即 使用了O_CREAT 时)才使用,用于指定文件的访问权限位(access permission bits)。pathname 是待打开/创建文件的POSIX路径名(如/home/user/a.cpp);flags 用于指定文件的打开/创建模式,这个参数可由以下常量(定义于fcntl.h)通过逻辑位或逻辑构成。
O_RDONLY 只读模式
O_WRONLY 只写模式
O_RDWR 读写模式

1.5ssize_t write (int fd,const void * buf,size_t count);

返回值:如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。

0)非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度 快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。

1)关于系统调用

read和write属于初级读写函数,也是系统调用;系统调用需要消耗大量时间。因为代码执行权会从用户转移到内核,执行内核代码是需要时间的。系统调用开销巨大,因为系统调用需要特殊的内存和堆栈环境,这些需要在系统调用之前建立好;系统调用之后又需要恢复这些环境。这种环境切换需要耗费大量时间。最好的方法就是建立缓冲区,一次读取大量数据,避免多次进行系统调用。我们可以用这个思想来改造前一篇中的who。

2)系统调用的错误处理

一般约定,系统调用open,write,lseek在出错时会返回值-1。另外,系统调用都有自己的错误集,以open为例,打开文件不存在,没有读的权限,打开文件太多等等。内核通过全局变量errno来确定错误类型,其中哦功能error.h中规定了一些错误的宏。

2.标准IO函数

2.1int fclose(FILE *stream);

如果流成功关闭,fclose 返回 0,否则返回EOF(-1)

2.2int feof(FILE *stream)

feof(fp)有两个返回值:如果遇到文件结束,函数feof(fp)的值为非零值,否则为0。

2.3int fgetc(FILE *stream);

这个函数的返回值,是返回所读取的一个字节。如果读到文件末尾或者读取出错时返回EOF。

2.4char *fgets(char *buf, int bufsize, FILE *stream)

fopen从文件结构体指针stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋'\0'),如果文件中的该行,不足bufsize个字符,则读完该行就结束。函数成功将返回buf,失败或读到文件结尾返回NULL。因此我们不能直接通过fgets的返回值来判断函数是否是出错而终止的,应该借助feof函数或者ferror函数来判断。bufsize的作用是防止缓冲区溢出。

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

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

r 以只读方式打开文件,该文件必须存在。
r+ 以可读写方式打开文件,该文件必须存在。
rb+ 读写打开一个二进制文件,允许读写数据
rw+ 读写打开一个文本文件,允许读和写。
w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。

2.6int fputc (int n, File *fp)

功能:输出一个字符到某个文件

2.7size_t fread ( void   *buffer,  size_t size,  size_t count,  FILE *stream) ;

size
单个元素的大小,单位是字节
返回值:
实际读取的元素个数.如果返回值与count不相同,则可能文件结尾或发生错误.
从ferror和feof获取错误信息或检测是否到达文件结尾.

2.8int fseek(FILE *stream, long offset, int fromwhere);

函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere(偏移起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
fseek函数和lseek函数类似,但lseek返回的是一个off_t数值,而fseek返回的是一个整型。

2.9size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream)

返回实际写入的数据项个数count。
说明:写入到文件的哪里? 这个与文件的打开模式有关,如果是w+,则是从file pointer指向的地址开始写,替换掉之后的内容,文件的长度可以不变,stream的位置移动count个数;如果是a+,则从文件的末尾开始添加,文件长度加大。

2.10int getc(FILE *stream);

注意: 此函数被ISO C声明为一个宏,所以在用时不能将其做为函数指针传(有一些编译器将其以函数形式也给另说)。

2.11getchar()

从stdio流中读字符,相当于getc(stdin),它从标准输入里读取下一个字符

2.12gets

从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。

2.13int fputc(char ch,FILE*fp)

putc()与fputc()等价。不同之处为:当putc函数被定义为宏时,它可能多次计算stream的值。

2.14 int putchar(int ch);

在标准输出上输出一个字符

2.15int puts(char *string);

功能:送一字符串到流stdout中

缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用,当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”, 装满后再从内存“缓冲区”依此读入接收的变量。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存 “缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。

3.格式化输出输出函数

3.1printf

3.2int fprintf(FILE *stream,char *format,[argument])

功能:格式化输出到一个流/文件中;

返回值:fprintf()的返回值是输出的字符数,发生错误时返回一个负值.

3.3scanf

3.4int fscanf(FILE *stream, char *format,[argument...]);

功 能: 从一个流中执行格式化输入,fscanf遇到空格和换行时结束,注意空格时也结束。这与fgets有区别,fgets遇到空格不结束。