【APUE】文件I/O

 

文件描述符

文件描述符通常是一个小的非负整数,内核用以标识一个特定进程正在访问的文件。

当内核打开一个文件或创建一个新文件时,它都返回一个文件描述符,用以读写文件。

每当运行一个程序时,所有的shell都为其打开三个文件描述符——标准输入(standard input)&标准输出(standard output)&标准错误(standard error)。

两个常量STDIN_FILENO和STDOUT_FILENO定义在头文件<unistd.h>中,它们指定了标准输入和标准输出的文件描述符,在POSIX标准中,它们的值分别是0和1。

六个函数

>open函数

功能:打开或创建一个文件

#include <fcntl.h>

int open( const char *path, int oflag, .../*mode_t mode*/ );

open 成功则返回文件描述符,出错则返回 -1

path: 要打开的文件、设备的路径名

oflag: 由多个选项进行或运算构造oflag参数

           必选:O_RDONLY(read only),  O_WRONLY(write only),  O_RDWR(read and write);

           可选:O_APPEND(每次写是追加在文件尾端)

                      O_CREAT(文件不存在即创建它,使用该选项需要第三个参数mode来指定打开文件的权限模式)

                      O_EXCL(用于测试一个文件是否存在,如果不存在则创建此文件)

                      // 文件已存在时,同时指定 O_EXCL 和 O_CREAT 会出错。

                      O_TRUNC(如果文件存在,而且为只写或者读写成功打开,则将其长度截短为0)

                      O_BOCTTY(如果 path 指的是终端设备,则不将该设备分配作为此进程的控制终端)    

                     O_NONBLOCK (如果 path 是一个 FIFO 、块设备、字符特殊文件,则此选项为文件的本次打开和后续 I/O 操作设置非阻塞模式方式)

>creat函数

功能:创建一个新文件

#include <fcntl.h>

int creat( const char *path, mode_t mode );

creat 成功则返回为只写打开的文件描述符,出错则返回 -1

此函数等价于   open( pathname, O_WRONLY | O_CREAT | O_TRUNC, mode );     

>close函数

功能:关闭打开的文件

#include <unistd.h>

int close( int fd );

colse 成功则返回0,出错则返回 -1

>lseek函数

功能:设置文件偏移量

#include <unistd.h>

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

lseek 成功做返回新的文件偏移量,若出错则返回 -1

whence: SEEK_SET (将该文件的偏移量设置为距文件开始处 offset 个字节)

                 SEEK_CUR (将该文件的偏移量设置为距当前偏移量 offset 个字节处,offset 可以为负)

                 SEEK_END (将该文件的偏移量设置为文件长度加 offset 个字节,offset 可以为负)

存疑:offset为负问题

若 lseek 成功执行,则返回新的文件偏移量,因此 lseek 可以用来确定打开文件的当前偏移量,或确定所涉及的文件是否可以设置偏移量。如果文件描述符引用的是一个管道、FIFO 或网络套接字,则 lseek 返回 -1,并将 errno 设置为 ESPIPE。

注意:由于某些设备允许负的文件偏移量,即返回负值时并不一定是 lseek 出错,所以在比较 lseek 的返回值时最好测试它是否等于 -1

>read函数

功能:从打开的文件中读数据

#include <unistd.h>

ssize_t read( int fd, void *buf, size_t nbytes );

read 成功则返回读到的字节数,出错则返回 -1

read 函数返回值为实际读到的字节数,所以不一定等于指定的读入字节数 nbytes。(读普通文件时在读到 nbytes 个字节前已经读到了文件尾端 | 从终端设备读入的字节限制 | 从网络读时的网络缓冲机制影响 | 从管道或FIFO读时管道包含的字节数小于 nbytes 从某些面向记录的设备读时的字节限制 | 信号中断而数据部分未读)

>write函数

功能:向打开的文件中写数据

#include <unistd.h>

ssize write( int fd,  );

write 函数的返回值通常与参数 nbytes 相同,否则表示出错。write出错的一个常见原因是:磁盘已写满,或者超过了一个给定进程的文件长度限制。

注意:对于普通文件,读操作和写操作都是从文件的当前偏移量开始,所以在调用 read 和 write 函数时一定要注意文件的当前偏移量位于文件的什么位置。(如果在打开文件时,指定了 O_APPEND 选项,则在每次操作之前,该文件的偏移量位于文件的当前结尾处,在一次成功写入之后,该文件的偏移量增加实际写的字数。)

>一个实例

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char **argv){
        int fd; 

        char buf1[] = "write successfully.";
        char buf2[] = "*******************";

        if((fd = open("forExample", O_RDWR | O_APPEND | O_CREAT, 0777)) < 0)
                printf("open error\n");
        printf("fd = %d\n", fd);//标准输入、输出、出错分别是0、1、2,于是fd取现在的最小数3

        if(write(fd, buf1, sizeof(buf1)) != sizeof(buf1))
                printf("write error\n");

        //此时文件偏移量在文件尾
        if(read(fd, buf2, sizeof(buf2)) < 0)
                printf("first read error");
        printf("first read:buf2 =  %s\n", buf2);

        lseek(fd, 0, SEEK_SET);
        //此时文件偏移量在文件头
        if(read(fd, buf2, sizeof(buf2)) < 0)
                printf("second read error");
        printf("second read:buf2 =  %s\n", buf2);
        //此时文件偏移量位于文件尾

        lseek(fd, -14, SEEK_CUR);
        //此时文件偏移量位于距离文件尾-6个字节处
        memset(buf2, 0, sizeof(buf2));
        if(read(fd, buf2, 7) < 0)
                printf("third read error");
        printf("third read:buf2 = %s\n", buf2);

        close(fd);

        return 0;
}

运行结果:

forExample文件内容:

为了体现代码中 open 函数选项的作用(再次打开时在文件尾端追加写入),再运行一次:

猜你喜欢

转载自blog.csdn.net/cxxya/article/details/81948941