1.符号描述符
首先要记住,对于所有打开的文件系统都是通过文件描述符来引用的。文件描述符是一个非负整数。在unix系统中(大部分系统也是这样),用0代表标准输入流,用1代表标准输出流,用2代表标准错误流。在头文件<unistd.h>中定义了STDIN_FILENO,STDOUT_FILENO以及STDERR_FILENO。
2.open函数
open函数可以打开或者创建一个文件,函数原型如下
#include <fcntl.h> int open(const char *pathname,int oflag,.../*mode_t mode*/) 返回值:若成功返回文件描述符,若出错返回-1
pathname不用说指的是文件的路径名,注意使用'/'来间隔目录。
对于第二个参数oflag,以下是需要使用到fcntl.h中的常用参数:
O_RDONLY(只读) O_WRONLY(只写) O_RDWR(读写) //以上这三个常量只能选择一个 O_APPEND(末尾追加) O_CREAT(如果文件不存在则创建文件,这时需要使用第三个参数mode,指定该文件的访问权限位) O_EXCL(如果文件存在,则出错,用来检测文件是否存在) O_TRUNC(如果文件存在,而且为只读或只写打开,则将其长度截短为1)
对于open函数,当且仅当创建新文件时才使用的三个参数。由open返回的文件描述符一定是最小的未用的文件描述符,这可以用先关闭标准输出,然后打开文件,则文件的描述符为1。
3.creat函数
creat函数用来创建一个新文件,函数原型如下
#includ <fcntl.h> int creat(const *pathname,mode_t mode) 返回值:若成功则返回为只写打开的文件描述符,否则返回-1 等效于open(pathname.O_WRONLY | O_CREAT | O_TRUNC,mode)
由于creat只能以写的方式打开文件,要想读取该文件需要creat,close,open。可以直接采用如下方式open(pathname,O_RDWR | O_CREAT |O_TRUNC,mode)。
4.close函数
关闭文件并释放其所占资源,函数原型如下
#include<unistd.h> int close(int filedes) 返回值:成功返回0,否则返回-1
5.lseek函数
每个打开的文件在内核中都维护了一个“当前文件偏移量”,指的是从文件开始处计算的字节数。除非使用O_APPEND,否则偏移量一般都为0。
调用lseek显示地为一个打开的文件设置偏移量,函数原型如下
#include <unistd.h> off_t lssek(int filedes, off_t offset, int whence) 返回值:若成功则返回新的文件偏移量,若出错则返回-1 //若whence为SEEK_SET,则将文件的偏移量设置为距文件开始处offset个字节。//// //若whence为SEEK_CUR,则将文件的偏移量设置为当前值加offset,offset可正可负。 //若whence为SEEK_END,,则将文件的偏移量设置为文件长度加offse,offset可正可负, //注意文件偏移量可以大于当前文件长度,系统并不会为之间的空洞分配磁盘空间,只为新的数据分配磁盘空间。
6.read函数
调用read函数从打开的文件中读取数据,函数原型如下:
#include <unistd.h> ssize_t read(int filedes,void *buf,size_t nbytes) 返回值:若成功返回读到的字节数,若已到文件结尾则返回0,若出错返回-1
7.write函数
调用write函数向打开的文件写数据,函数原型如下:
#include <unistd.h> ssize_t write(int filedes,const void* buff,size_t nbytes) 返回值:若成功返回已写的字节数,若出错返回-1
其返回值通常与参数nbytes相同,否则表示出错。常见的出错原因包括:磁盘已经写满、超过了文件的最大长度限制。对于普通文件,写操作从文件的当前偏移量处开始。执行一次成功的写之后,文件的偏移量增加实际写的字节数。
8.文件I/O函数总结
1).进程终止时,uinx系统内核会关闭该进程的所有打开的文件描述符,所以可以不用必须关闭输入和输出文件(最好还是自行关闭,以免造成内存资源的浪费)。
2).上述的open、creat、close、lseek、read、write都是系统内核函数,对文本文件和二进制文件没有区别。
3).用以下程序来实践一下。
#include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h> #define BUFFSIZE 2048 int main(int argc,char **argv) { int fd,num; char buf[BUFFSIZE]; char *fileName = "./1.txt"; off_t pos; // 在当前目录下以读写的方式打开文件,若文件不存在则创建文件 if(( fd = open(fileName,O_RDWR | O_CREAT | O_TRUNC)) < 0) { printf("open file fail%s\n",fileName); exit(1); } //从键盘读入数据,再写入到文件中 while((num = read(STDIN_FILENO,buf,BUFFSIZE)) > 0) { //如果为"stop"则停止输入 if(strncmp(buf,"stop",4)==0) { printf("write data stop\n"); break; } if(write(fd,buf,num) != num) { printf("write data fail\n"); exit(1); } printf("write data success\n"); } //在文件最后的第10个字节出插入"?" if((pos = lseek(fd,-10,SEEK_END)) == -1) { printf("lssek fail\n"); exit(1); } if(write(fd,"?",1) != 1) { printf("read fail\n"); exit(1); } return 0; }
注意:这里的文件creat时没有设置权限,所以读取时要用到root权限。运行结果如下:(可以尝试把偏移量设置为10,运行下结果看看)