一、标准IO
标准I/O指的是ANSIC中定义的用于I/O操作的一系列函数,所需头文件:#include<stdio.h>
流:
标准I/O都是基于流进行操作,当用标准I/O打开一个文件时,就会创建一个FILE结构体来描述这个文件,我们把这个结构体形象地称为流。
流的打开和关闭:
使用标准I/O打开流的函数有:fopen()/fdopen()/freopen(),它们可以以不同模式打开文件,都返回一个指向FILE的指针,该指针指向对应的I/O流。关闭流的函数fclose(),将流的缓冲区的数据全部写入文件中,并释放相关资源。
fopen()函数:
函数原型:FILE *fopen(const char *path , const char *mode);
path :要打开的文件路径及文件名
mode :文件打开方式
r或者rb :只读,文件必须存在
r+或者r+b :可读写,文件必须存在
w或者wb :只写(擦写),文件不存在则创建
w+或者w+b :可读写(擦写),文件不存在则创建
a或者ab :只写(追加写),文件不存在则创建
a+或者a+b :可读写(追加写),文件不存在则创建
(注意:每个选项加入b字符,是用来告诉函数库打开的是二进制文件,而非纯文本文件,不过在Linux系统中会忽略该符号)
函数返回值:成功:指向FILE的指针;失败:NULL
fclose()函数:
函数原型:int fclose(FILE *stream);
stream :已打开的流指针
函数返回值:成功:0;失败:EOF
perror()函数:
函数原型: void perror(const char *s);
s :输出信息
strerror()函数:
函数原型:char *strerror(int errnum);
errno:全局错误码(全局变量)
函数返回值:错误码对应的错误信息
按字符输入函数:
函数原型:int getc(FILE *stream);
int fgetc(FILE *stream);
int getchar( );
stream:要输入的文件流
函数返回值:成功:读取的字符;失败:EOF
按字符输出函数:
函数原型:int putc(int c , FILE *sream);
int fputc(int c , FILE *sream);
int putchar(int c);
函数返回值:成功:输出的字符c;失败:EOF
按行输入函数:
函数原型:char *gets(char *s);
char *fgets(char *s , int size , FILE *stream);
s :存放输入字符串的缓冲区首地址
size :输入的字符串长度
stream :对应的流
函数返回值:成功:s;失败或到达文件末尾:NULL
按行输出函数:
函数原型:int puts(const char *s);
int fputs(const char *s , FILE *stream);
s :存放输出字符串的缓冲区首地址
stream :对应的流
函数返回值:成功:非负数;失败:EOF
fread()函数:
函数原型:int fread(void *buf , size_t size , int nmemb , FILE *stream);
buf : 存放读取的缓冲区
size :读取的每个记录的大小
nmemb :读取的记录数
stream :要读取的文件流
函数返回值:成功:实际读取的数目;失败:EOF
fwrite()函数:
所需头文件:#include<stdio.h>
函数原型:int fwrite(void *buf , size_t size , int nmemb , FILE *stream);
buf : 存放写入的缓冲区
size :写入的每个记录的大小
nmemb :写入的记录数
stream :要写入的文件流
函数返回值:成功:实际写入的数目;失败:EOF
fseek()函数:
所需头文件:#include<stdio.h>
函数原型:int fseek(FILE *stream , long offset , int whence);
stream : 要定位的文件流
offset :相对于基准值的偏移量
whence :基准值
SEEK_SET :文件起始位置
SEEK_CUR :文件当前读写位置
SEEK_END :文件结束位置
函数返回值:成功:0;失败:EOF
ftell()函数:
所需头文件:#include<stdio.h>
函数原型: long ftell(FILE *stream);
stream : 要定位的文件流
函数返回值:成功:当前读写位置;失败:EOF
opendir()函数;
函数原型:DIR *opendir(const char *name);
name :目录名
函数返回值:成功:可用的目录流;失败:NULL,并置errno
readdir()函数:
函数原型:struct dirent *readdir(DIR *dir);
dir :要读取的目录流
函数返回值:成功:struct dirent 结构体首地址,读到结尾,返回NULL,并且errno不变
失败:NULL,并置errno
struct dirent {
ino_t d_ino ; //目录文件inode号
off_t d_off ; //在目录文件中的偏移
unsigned short d_reclen ; //目录文件名长
unsigned char d_type ; //文件类型
char d_name[256] ; //文件名
};
d_type的取值类型如下:
DT_BLK this is a block device.
DT_CHR this is a character device .
DT_DIR this is a directory .
DT_FIFO this is a named pipe (FIFO).
DT_LNK this is symbolic link .
DT_REG this is regular file .
DT_SOCK this is a UNIX domain socket .
二、文件IO
文件I/O指的是由POSIX标准来定义的用于I/O操作的一系列函数。
open()函数:
用于打开或创建一个文件,在打开或创建文件时可以指定文件打开方式及文件访问权限。
函数原型:int open(const char *pathname , int flags , int perms);
pathname : 被打开的文件名
flags : 打开方式
O_RDONLY 只读;
O_WRONLY 只写;
O_RDWR 读写;
O_CREAT 若文件不存在则创建;
O_EXCL 若创建时文件存在,则返回错误消息;
O_NOCTTY 使用本参数,若打开的是终端文件,那么该终端不会成为当前进程的控制终端
O_TRUNC 若文件已经存在,那么会删除文件原有数据
O_APPEND 以添加方式打开文件,在写文件时,文件读写位置自动指向文件末尾
perms : 新建文件的存取权限
可以用一组宏定义:S_I(R/W/X)(USR/GRP/OTH)
也可用八进制:如0777
函数返回值:成功:文件描述符 失败:-1
close()函数:
用于关闭一个被打开的文件。
函数原型:int close(int fd);
fd : 文件描述符
函数返回值:成功:0 失败:-1
read()函数:
从文件中读取数据,存放到缓冲区,并返回实际读取的字节数。
函数原型:int read(int fd , void *buf , int count);
fd : 文件描述符
buf :指定存储器读出数据的缓冲区
count :指定读出的字节数
函数返回值:成功:读到的字节数,0:已到达文件尾;失败:-1
write()函数:
将数据写入文件中,并返回实际写入的字节数。
函数原型:int write(int fd , void *buf , int count);
fd :文件描述符
buf :指定存储器写入数据的缓冲区
count :指定写入的字节数
函数返回值:成功:写入的字节数;失败:-1
lseek()函数:
对文件当前读写位置进行定位,它只能对可定位文件操作(管道、套接字和部分字符设备文件不支持)。
函数原型:int lseek(int fd , int offset , int whence);
fd :文件描述符
offset :相对于基准点whence的偏移量
whence :当前位置的几点
SEEK_SET 文件的起始位置
SEEK_CUR 文件当前读写位置
SEEK_END 文件结束位置
函数返回值:成功:文件当前读写位置;失败:-1
三、标准IO与文件IO的区别
标准IO和文件IO都可以用来访问文件,那么他们之间有什么区别呢?
1、文件IO又称为低级磁盘IO,遵循POSIX相关标准,任何支持POSIX标准的操作系统上,都支持文件IO。
2、标准IO又称为高级磁盘IO,遵循ANSIC相关标准,只要开发环境中有标准C库,都支持标准IO。
Linux中使用的是glibc,它是标准C库的超集,不仅包含POSIX标准定义的函数,还包含ANSIC中定义的函数,所以在Linux下,既可以使用标准IO,也可以使用文件IO。
通过文件IO读写文件时,每次操作都会执行相关系统调用。这样处理的好处是可以直接读写实际文件,坏处是频繁地系统调用会增加系统开销;而标准IO可以看做是在文件IO的基础上封装了缓冲机制,先读写缓冲区,必要时再访问实际文件,从而减少系统调用次数。
文件IO中用文件描述符表示一个打开的文件,可以访问不同类型的文件(如普通文件、设备文件和管道文件)。而标准IO中用FILE(流)表示一个打开的文件,通常只用来访问普通文件。