引言
上一章笔记主要是简介系统IO,以及Open函数的使用,那么这一章下来可能比较长,因此分为上、下两部分。打算一次性将系统IO的核心部分API记录完。本章主要以例子介绍以下内容:read、write、lseek文件位置偏移等介绍与使用。
read与write的使用(cp命令的原理)
要读一个文件,首先还得使用上一篇笔记介绍的open函数,大概的思路为:
假设我们将a.txt复制为b.txt,那么在复制的过程中,其实就是一个新建b.txt文件,将a.txt文件内容写入b.txt的一个过程:
- 第一步:首先要用open将a.txt打开,判断是否存在b.txt,如果不存在则新建一个。
- 第二步:将a.txt里面的内容,读到缓冲区(内存),然后再将缓冲区的数据写入b.txt中
- 在电脑的运行过程中,并不会太理想的就是:缓冲区可能只有100字节的大小,而我们假设a.txt占用2000字节,那么我们就应该不断地读,不断地写入。
- 更加不理想的是绿色的情况,假如缓冲区100个字节,但是实际上这一次仅仅读了80个字节,而写入仅仅写了50个字节的情况也时有发生。
代码实现
值得注意的地方是这里:
read函数不会保证会读满整个缓冲区
那么write函数也不会保证一次性能把整个缓冲区写入
那么要解决这个问题,就需要下面这个操作:
为了说明这个操作:我们举例 这个buf里面有100个字节,但是write第一次只写了80字节,也就是返回值nwrite=80(绿色):
- 第一次(绿色)写了80字节,那么write语句应该为
write(fd,buf,80)
- 还剩余20字节没有写完,那么write函数中的Buf指的是整个缓冲区,那么如果继续使用buf,read函数一边在读,会导致后面的20个字节不能按照正确写入文件中。
- 因此要定义一个指针p指向Buf,所以第二次写(黄色)的write语句:
write(fd,p+80,20)
才是正确的操作 - 那么,将以上例子整合成代码:
write(fd_dst,p,nread)
nread -= nwrite
p += nwrite
- 假设write很成功一次性写完缓冲区的数据到文件中,那么nread-nwrite=0,符合逻辑。
代码验证:
lseek文件位置偏移
在我们刚刚使用read、write去读写文件的时候,每次读写的数目都不一样,但是系统都有办法去记录它。那么这个就叫做文件的位置偏移。
我们可以使用lseek去调整文件位置:
例如要将当前位置b调整为a的位置
那么调整的方法有三种:
- 可以调节为距离开头位置100个字节的地方
- 可以调节为距离当前位置b -10个字节的地方
- 可以调节为距离结尾位置 -180个字节的地方
下面来编写一个能够将文件读取两边的代码来介绍lseek的作用:
lseek的使用 | 作用 |
---|---|
功能 | 调整文件位置偏移量 |
头文件 | < sys/types.h > < unistd.h > |
函数原型 | lseek(int fd, offset,int whence); |
参数fd | 要调整的位置偏移量的文件的描述符 |
参数offset | 新位置偏移量相对基准点的偏移 |
参数whence | SEEK_SET:文件开头处 |
参数whence | SEEK_CUR:当前位置 |
参数whence | SEEK_END:文件末尾处 |