文件IO(2)--read、write和lseek
昨天我们学习了open和creat函数,今天我们继续学习write、read和lseek函数,他们均定义在<unistd.h>。
1. read函数
1) 函数原型:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
2) 函数功能:
read系统调用从文件描述符fd指向的文件中,读取count个字节到buf中。
3) 参数说明:
fd:文件描述符
buf:保存读入信息的缓存
count:要读取的字节数
返回值:如果read成功,则返回读到的字节数,如果已达到结尾,则返回0,出错
返回-1
2. write函数
1) 函数原型:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
2) 函数功能:
write系统调用将buf所指向的缓冲区的count个字节内容写入fd指向的文件
3) 参数说明:
fd:要写入的文件
buf:要写入的信息所在的缓存
count:要写入的字节数
返回值:如果write成功,则返回写入的字节数,出错返回-1
3. lseek函数
1) 函数原型:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fildes, off_t offset, int whence);
2) 函数功能:
lseek系统调用用来移动读写指针的位置
3) 参数说明:
fd:要操作的文件
offset:相对whence移动的位移数,允许负值
whence:起始指针,它有三个取值
SEEK_SET 从文件开始处计算偏移量
SEEK_CUR 从文件指针的当前位置开始计算偏移量
SEEK_END 从文件结尾处开始计算偏移量
文件指针值等于当前指针值加上offset的值。
返回值:调用成功时范围当前的读写位置,也就是距离文件开始处多少字节,若
有错误返回-1
4) 常见用法:
将文件读写指针移动到文件开头:
lseek(int fildes, 0, SEEK_SET);
将文件读写指针移动到文件结尾:
lseek(int fildes, 0, SEEK_END);
获取文件读写指针当前的位置
lseek(int fikdes, 0, SEEK_CUR);
注意:有些设备(或者说设备文件)不能使用lseek,linux系统不允许lseek()对tty设备进行操作,此项操作会使得lseek()范围错误代码ESPIPE
4.实例程序:
1)演示文件读写和文件指针的移动过程:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> void my_error(const char* errstring, int line) { fprintf(stderr,"line:%d",line); perror(errstring); exit(1); } int my_read(int fd) { int len = 19,ret,i; char buf[128]; if((lseek(fd,0,SEEK_END)) == -1) { my_error("lseek",__LINE__); } if((len = lseek(fd,0,SEEK_CUR)) == -1) { my_error("lseek",__LINE__); } if((lseek(fd,0,SEEK_SET)) == -1) { my_error("lseek",__LINE__); } printf("文件长:%d\n",len); if((ret = read(fd,buf,len)) == -1) { my_error("read",__LINE__); } for(i=0;i<len;i++) { printf("%c",buf[i]); } printf("\n"); } int main() { int fd; char buf[128] = "my name is haohuai!"; umask(0000); if((fd = open("test.txt",O_RDWR | O_CREAT | O_TRUNC,0777)) == -1) { my_error("open",__LINE__); } else { printf("open success!\n"); } if(write(fd,buf,strlen(buf)) != strlen(buf)) { my_error("write",__LINE__); } else { printf("write success!\n"); } my_read(fd); return 0; }
注:1)其中__LINE__是预编译器内置宏,表示当前行,类似的还有__TIME__、
__FUNCTION__ 、__FILE__等,表示时间、函数名、文件名。
2)read读取文件之前一定要先将文件指针指向文件开始处,否则文件指针处
于文件结尾处。
运行结果:
[hb@localhost unixadvance]$ gcc -g -o testWRL testWRL.c
[hb@localhost unixadvance]$ ./testWRL
open success!
write success!
文件长:19
my name is haohuai!
2)将标准输入复制到标准输出
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #define SIZE 1024 int main() { int n ; char buf[SIZE]; while((n = read(STDIN_FILENO,buf,SIZE)) > 0) { if(write(STDOUT_FILENO,buf,n) != n) { perror("write error"); } } if(n < 0) { perror("read error"); } return 0; }
注:STDIN_FILENO和STDOUT_FILENO分别是标准输入和标准输入的文件描述
符,一般是0和1,定义在<unistd.h>