1.read函数
调用read函数从文件去读数据,函数定义如下:
#include <unistd.h> ssize_t read(int filedes, void* buff, size_t nbytes);成功则返回实际读取的byte数,如果已经达到文件结尾则返回0,出错则返回-1.
2.write函数
调用write函数向打开的文件写入数据,函数定义如下:
#include <unistd.h> ssize_t write(int filedes, void* buff, size_t nbytes);成功则返回实际写入的byte数,出错则返回-1.
3.lseek函数
每个打开的文件都有一个关联的“当前偏移量”,用于记录从文件到当前当前位置的偏移字节数,lseek函数是设置这个当前偏移量
的函数,函数的声明如下:
#include <unistd.h> off_t lseek(int filedes, off_t offset, int whence);成功则返回新的文件偏移量,失败则返回-1.
如果whence是SEEK_SET,则文件的偏移量设置为文件开始加上offset个字节。
如果whence是SEEK_CUR,则文件的偏移量设置为当前偏移量开始加上offset个字节,offset可正可负。
如果whence是SEEK_END,则文件的偏移量设置为文件长度加上offset个字节,offset可正可负。
不是每个文件都能够设置偏移量,有些文件如管道,FIFO或socket,无法设置偏移量,可以使用如下函数测试是否可以设置偏移量,
如果返回-1,则表示不可以。
off_t currpos; currpos = lseek(fd, 0, SEEK_CUR);
2.实践
创建一个文件,往文件中写入10个字符,然后再使用lseek定位文件开始加上4个字节的偏移量,然后读取接下来的内容。
#include <fcntl.h> #include <stdio.h> int main(void){ int fd,byteNum,result; char wbuf[10] = "123456789"; char rbuf[10]; if((fd = open("./a.txt", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){ perror("open"); return -1; } if((byteNum = write(fd, wbuf, 10))<0){ perror("write"); return -1; } if((result = lseek(fd, 4, SEEK_SET))<0){ perror("lseek"); return -1; } if((byteNum = read(fd, rbuf, 10)) < 0){ perror("read"); return -1; } printf("read content:%s ",rbuf); close(fd); return 0; }运行结果:
read content:56789
如果将偏移量设置为文件开始加上一个负数,调用lseek就会出错。
#include <fcntl.h> #include <stdio.h> int main(void){ int fd,byteNum,result; char wbuf[10] = "123456789"; char rbuf[10]; if((fd = open("./a.txt", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){ perror("open"); return -1; } if((byteNum = write(fd, wbuf, 10))<0){ perror("write"); return -1; } if((result = lseek(fd, -1, SEEK_SET))<0){ perror("lseek"); return -1; } if((byteNum = read(fd, rbuf, 10)) < 0){ perror("read"); return -1; } printf("read content:%s ",rbuf); close(fd); return 0; }运行结果:
lseek: Invalid argument
是不是offset就一定不能为负数呢,不一定,只要最终的偏移量不小于0就可以了,看下面的例子。
#include <fcntl.h> #include <stdio.h> int main(void){ int fd,byteNum,result; char wbuf[10] = "123456789"; char rbuf[10]; if((fd = open("./a.txt", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){ perror("open"); return -1; } if((byteNum = write(fd, wbuf, 10))<0){ perror("write"); return -1; } if((result = lseek(fd, -4, SEEK_CUR))<0){ perror("lseek"); return -1; } if((byteNum = read(fd, rbuf, 10)) < 0){ perror("read"); return -1; } printf("read content:%s ",rbuf); close(fd); return 0; }运行结果:
read content:789
如果文件偏移量大于文件长度再写入数据,那么生成的文件就会出现空洞。先往文件写入10个字符,再跳过20个字符,再写入10个字符。
#include <fcntl.h> #include <stdio.h> int main(void){ int fd,byteNum,result; char wbuf[10] = "123456789"; char rbuf[10]; if((fd = open("./a.txt", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR))<0){ perror("open"); return -1; } if((byteNum = write(fd, wbuf, 10))<0){ perror("write"); return -1; } if((result = lseek(fd, 40960, SEEK_END))<0){ perror("lseek"); return -1; } if((byteNum = write(fd, wbuf, 10)) < 0){ perror("write"); return -1; } close(fd); return 0; }运行结果:
-rw------- 1 root root 40980 2013-09-09 15:03 a.txt
使用od命令查看文件内容:
root@virtual-machine:~# od -c a.txt