(1) read()
形式:#include<unistd.h>
ssize_t read (int filedes, void *buf, size_t nbytes );
成功:返回读到的字节数;出错:返回-1;文件尾:返回0;
原因:基本系统调用功能;
实现:文件(由filedes所指)-读nbytes字节->内存buf中。
补充:有多种情况可使实际读到的字节数少于要求读的字节数:
当从普通文件读时,在读到要求字节数之前已到达了文件尾端。
当从终端设备读时,通常一次最多读一行。
当从网络读时,网络中缓冲机构可能造成返回值小于所要求读的字节数。
当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么只返回实际用的字节数。
当从某些面向记录的设备读时,一次最多返回一个记录。
当某一信号造成中断,而已经读了部分数据量时。
读操作从文件的当前偏移量处开始,在成功返回之前,该偏移量将增加实际读到的字节数。常用的unix系统shell都提供一种方法,它在标准输入上打开一个文件,在标准输出上追寻或重写一个文件,这使得程序不必自行打开输入和输出文件。
(2) write()
形式:#include<unistd.h>
ssize_t write (int filedes, const void *buf, size_t nbytes );
成功:返回已写的字节数;出错:返回-1;
原因:基本系统调用功能;
实现:文件(由filedes所指)<-写nbytes字节-内存buf中。
补充:write出错的一个常见的原因是:磁盘已写满,或者超过了一个给定进程的文件长度限制。对于普通文件,写操作从文件的当前偏移量处开始。如果在打开该文件时,指定了O_APPEND选项,则在每次写操作之前,将文件偏移量设置在文件的当前结尾处。在一次成功写之后,该文件偏移量增加实际写的字节数。
(3) pread()
形式:#include<unistd.h>
ssize_t pread (int filedes, void *buf, size_t nbytes, off_t offset );
成功:返回读到的字节数;出错:返回-1;到文件结尾:返回0
原因:由于lseek和read 调用之间,内核可能会临时挂起进程,所以对同步问题造成了问题,调用pread相当于顺序调用了lseek 和 read,这两个操作相当于一个捆绑的原子操作。
实现:文件(由filedes所指)-读nbytes字节->内存buf中。
补充:调用pread时,无法中断其定位和读操作,另外不更新文件指针。
(4) pwrite()
形式:#include<unistd.h>
ssize_t pwrite (int filedes, const void *buf, size_t nbytes, off_t offset );
成功:返回已写的字节数;出错:返回-1;
原因:由于lseek和write 调用之间,内核可能会临时挂起进程,所以对同步问题造成了问题,调用pwrite相当于顺序调用了lseek 和 write,这两个操作相当于一个捆绑的原子操作。
实现:文件(由filedes所指)<-写nbytes字节-内存buf中。
补充:调用pwrite时,无法中断其定位和读操作,另外不更新文件指针。
2. 流(stream)或标准I/O( 进程->fp->流(FILE+缓冲)->文件)(内存buf, 流fp):
每次输入一个字符:
(1) getc();
格式:#include <stdio.h>
int getc(FILE *fp);
成功:返回下一个字符;出错:返回EOF;文件尾:EOF;
实现:内存 <-读一个字符c- 流(由fp所指的流,是文件的逻辑代表)
原因:在标准I/O中用,将流看成文件的逻辑代表,将对进程->文件的操作,现转换为进程->流(也就是相当于文件)的操作。
补充:函数在返回下一个字符时,会将其unsigned char类型转换为int类型。为不带符号的理由是,如果最高位是1也不会使返回值为负。要求整形返回值的理由是,这样就可以返回所有可能的字符值再加上一个已出错或已到达文件尾端的指示值。即字符值变为正的int值,负的值就是出错或是到达文件尾端。(负值表特殊意义),