【APUE】第3章 文件I/O (2) 函数creat、lseek、read、write使用说明

时间:2021-04-30 19:07:58

1、函数creat

可以使用creat函数创建一个新文件。

1 #include<fcntl.h>
2 int creat(const char *path, mode_t mode);
3 
4 返回值:
5 若成功,返回为只写打开的文件描述符;
6 若失败,返回-1

上述函数原型等价于:

1 open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);

使用creat函数的一个不足之处是它以只写的凡是打开创建的新文件。在没有open新版本函数之前,如果要创建一个临时文件,并要先写该文件,然后又读该文件,则必须先调用creat、close,然后再调用open。即可以使用下列方式实现:

1 open(path, O_RDWR | O_CREAT | O_TRUNC, mode);

一般直接使用open函数替代creat函数

 

2、函数lseek

每个打开的文件都有一个与之相关联的“当前文件偏移量”(current file offset)。它通常是一个非负整数(通常是),用以度量从文件开始处计算的字节数。通常,读、写操作都是从当前文件偏移量处开始并使偏移量增加所读写的字节数。按系统默认情况下,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置成0。

可以调用lseek函数显示地为一个打开的文件设置偏移量

1 #include<unistd.h>
2 off_t lseek(int fd, off_t offset, int whence);
3 
4 返回值:
5 若成功,返回新的文件偏移量
6 若失败,返回-1

对参数offset的解释与参数whence的值有关:

  • 若whence是SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节。
  • 若whence是SEEK_CUR,则将该文件的偏移量设置为其当前值加offset,offset可正可负
  • 若whence是SEEK_END,则将该文件的偏移量设置为文件长度加offset,offset可正可负。

若lseek成功执行,则返回新的文件偏移量,为此可以使用下列方式确定打开文件的当前的偏移量:

1 off_t currpos;
2 currpos = lseek(fd, 0, SEEK_CUR);

这种方法也可以用来确定涉及的文件是否可以设置偏移量。如果文件描述符指向的是一个管道、FIFO或者网络套接字,则lseek返回-1,并将errno设置为ESPIPE。

通常,文件的当前偏移量应当是一个非负整数,但是某些设备可能允许负的偏移量。但是对于普通文件,其偏移量必须是非负值。因为偏移量可能是负值,所以在比较lseek的返回值时需要谨慎,不要测试它是否小于0,而要测试它是否等于-1

lseek仅将当前的文件偏移量记录在内核中,它并不引起任何I/O操作。然后,该偏移量用于下一个读操作或者写操作。

文件的偏移量是可以大于当前文件的长度,在这种情况下,对该文件的下一次写将加长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被读为0。

文件中的空洞并不要求在磁盘中占用存储空间,具体处理方式与文件系统的实现有关,当定位到超出文件尾端之后写时,对于新写的数据需要分配磁盘快,但是对于原文件尾端和新开始写位置之间的部分则不需要分配磁盘块。

 

3、函数read

对于内核而言,所有打开的文件都通过文件描述符引用。文件描述符是一个非负整数。当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符。当读或写一个文件时,使用open或creat返回的文件描述符表示该文件,将其作为参数传给read或write函数。

 1 头文件:#include<unistd.h> 
 2 功能:用于从文件描述符对应的文件读取数据(从打开的设备或文件中读取据---从文件描述符fd中读count个字节的数据到buf中 3 ssize_t read(int fd, void*buf, size_t count)
 4 参数说明:
 5 fd:        是文件描述符
 6 buf:      为读出数据的缓冲区;
 7 count:  为每次读取的字节数(是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移)
 8 返回值说明:
 9 成功:返回读出的字节数
10 失败:返回-1,并设置errno,如果在调用read之前到达文件末尾,则这次read返回0

有几种情况可使实际读到的字节数少于要求读的字节数:

(1)读普通文件时,在读到要求字节数之前就已经达到了文件末端。例如,若在到达文件末端之前还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它将返回0(文件末端)。

(2)当从终端设备读时,通常一次最多读一行。

(3)当从网络读时,网络中的缓存机制可能造成返回值小于所要求读的字结束。

(4)当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么read将只返回实际可用的字节数。

(5)当从某些面向记录的设备(例如磁带)读时,一次最多返回一个记录。

(6)当某一个信号造成中断,而已经读取了部分数据。

 

4、函数write

 1 #include <unistd.h>
 2 功能:用于向文件描述符对应的文件写数据(将buf中的人count个字节的数据写入文件描述符fd指向的文件中 3 ssize_t write(int fd, const void*buf, size_t count); 
 4 参数说明: 
 5 fd:是文件描述符(write所对应的是写,即就是1) 
 6 buf:通常是一个字符串,需要写入的字符串 
 7 count:是每次写入的字节数 
 8 返回值: 
 9 成功:返回写入的字节数 
10 失败:返回-1并设置errno 
11 ps:写常规文件时,write的返回值通常等于请求写的字节数count, 而向终端设备或者网络写时则不一定