read函数用于从打开的文件中读取数据,函数原型如下:
#include <unistd.h>
ssize_t read(int filedes, void *buf, size_t nbyetes);
返回值:如果读成功则返回实际读到的字节数,若已读到文件结尾则返回0,若出错则返回-1。
参数:
1、filedes 文件标识符,由调用open函数从内核获得。
2、*buf 存放所读数据的缓冲区地址。
3、nbytes 需要从文件中读取的数据字节数。
实例 x.3.7.1.c
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define BUFFSIZE 256
int main(void)
{
char pathname[] = "/tmp/myfile"; /*文件路径*/
int fileid; /*文件标识符*/
off_t f_offset; /*偏移量*/
ssize_t nread; /*读到的字节数*/
char buf[BUFFSIZE]; /*数据缓冲器*/
size_t nbytes; /*要读的字节数*/
/*打开文件,获取文件标识符*/
fileid = open(pathname, O_RDONLY | O_CREAT);
if (fileid == -1) {
printf("open error for %s\n", pathname);
return 1;
}
/*定位文件读位置(当前文件偏移量)*/
f_offset = lseek(fileid, 0, SEEK_SET);
if (f_offset == -1) {
printf("lseek error for %s\n", pathname);
return 2;
}
/*从文件中读取数据*/
nbytes = 3; /*设置要读取的字节数*/
nread = read(fileid, buf, nbytes); /*调用read函数读取数据*/
if (nread == -1) { /*判断读操作是否成功*/
printf("read error for %s\n", pathname);
return 3;
}
nread = nread == 0 ? nbytes : nread; /*求实际读到的字节数*/
/*read函数不会在最后自动加上字符串结束符,所以要在nread位置加上'\0'*/
/*否则调用printf打印字符时会超越nread位置,从而导致不可知情况,甚至出错*/
/*如果不是调用数据不是作为一个字符或者不是调用printf打印字符就没必要这么做*/
buf[nread] = '\0';
printf("data is:%s\n", buf);
close(fileid);
return 0;
}
编译与执行:
data is:012[root@localhost unixc]# echo "0123456789" > /tmp/myfile
[root@localhost unixc]# cat /tmp/myfile
0123456789
[root@localhost unixc]# cc x.3.7.1.c
[root@localhost unixc]# ./a.out
data is:012
[root@localhost unixc]#
注意:
read函数虽然有一个参数nbtyes指定要读取的字节数,但有时候未必能读到指定的数量的数据。这几种会导致实际读到的字节数nread小于指定的字节数nbytes:
1、读普通文件时,在未读到指定字节数的数据时,已经读到了文件的结尾。
2、从终端设备(例如标准输入)读数据时,nbytes大于终端设备每行最多的字节数。
3、从网络设备读数据时,网络设备的缓冲区所存数据小于nbytes。
4、从管道或者FIFO读数据时,管道里面包含的字节数小于nbytes。
所以,不用简单地把read的返回值nreade或者nbytes作为实际读到的字节数。
nread = nread == 0 ? nbytes : nread;可以断定实际读到的字节数。