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,运行下结果看看)