my_rwl.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
//自定义错误处理函数
void my_err(const char *err_string,int line)
{
fprintf(stderr,"line:%d ",line); //标准错误输出
perror(err_string); //输出错误原因
exit(1);
}
//自定义读数据函数
int my_read(int fd)
{
int len;
int ret;
int i;
char read_buf[64];
//获取文件长度并保持文件读写指针在文件开始处
if(lseek(fd,0,SEEK_END)==-1) //将文件读写指针移动到文件末尾,有错误返回-1
{
my_err("lseek",__LINE__); //调用错误处理函数,定位错误
}
if((len=lseek(fd,0,SEEK_CUR))==-1) //获取文件读写指针的当前位置
{
my_err("lseek",__LINE__); //__LINE__为预编译器内置宏,表示行数
}
if(lseek(fd,0,SEEK_SET)==-1) //将文件读写指针移动到文件开头
{
my_err("lseek",__LINE__);
}
printf("len:%d\n",len); //打印文件长度
//读数据
if((ret=read(fd,read_buf,len))<0) //调用read函数
{
my_err("read",__LINE__);
}
//打印数据
for(i=0;i<len;i++)
printf("%c",read_buf[i]);
printf("\n");
return ret; //ret为实际读到字节数
}
int main()
{
int fd;
char write_buf[32]="Hello World!";
//在当前目录下创建文件example_2.c
//if((fd=creat("example_2.c",S_IRWXU))==-1)
if((fd=open("example_2.c",O_RDWR|O_CREAT|O_TRUNC,S_IRWXU))==-1)
{
my_err("open",__LINE__);
}
else
{
printf("create file success\n");
}
//写数据
if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf))
//返回值与写入字节数不相等,有错误发生
{
my_err("write",__LINE__);
}
my_read(fd); //调用自定义读数据函数
//演示文件的间隔
printf("————————————————————————————————————————————\n");
if(lseek(fd,10,SEEK_END)==-1) //文件偏移量被设置为文件长度12+10,即22
{
my_err("lseek",__LINE__);
}
if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf))
//在文件第23个字节处开始再写12个字节
{
my_err("write",__LINE__);
}
my_read(fd); //读了共34个字节长度
close(fd);
return 0;
}
首先在当前目录下创建了example_2.c。
因为open的参数为O_RDWR|O_CREAT|O_TRUNC表示以可读可写创建一个文件,如果该文件存在,则将原文件数据清0,即覆盖掉。
然后向新创建文件写入数据。
read函数测试文件长度,然后读出全部数据,并且打印出来。
程序执行完后查看文件内容:
如果write对EOF之后的位置写入了数据,EOF之前与EOF之后的数据之间将会存在一个间隔,由上图中的ASCII码知,间隔中的数据为0。
read函数:
1.原型:
#include<unistd.h>
ssize_t read(int fd, void *buf,size_t count);
2.功能:
从打开的设备或文件中读取数据。
3.参数:
count是请求读取的字节数,从fd所指向的文件中读上来的数据保存在缓冲区buf中。同时文件读写指针也会随读到的字节移动。
注意返回值类型是ssize_t,表示有符号的size_t,这样既可以返回正的字节数、0(表示到达文件末尾)、也可以返回负值-1(表示出错)。
write函数:
1.原型:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
2.功能:
向打开的设备或文件中写数据。
3.参数:
count是请求写入的字节数,把缓冲区buf中的数据写入到由fd所指向的文件中。同时文件读写指针也会随之移动。
lseek函数:
1.原型:
#include <unistd.h>
#include <sys/types.h>
off_t lseek(int filedes, off_t offset, int whence);
2.功能:
每一个已打开的文件都有一个读写位置,当打开文件时通常其读写位置是指向文件开头,若是以添加的方式打开文件(如O_APPEND),则读写位置会指向文件尾。当read()或write()时,读写位置会随之增加,lseek()便是用来控制该文件的读写位置。参数fildes 为已打开的文件描述符,参数offset 为根据参数whence来移动读写位置的位移数。
3.参数:
① filders:已打开的文件描述符。
② offset:根据参数whence来移动读写位置的位移数。
③ whence:取值有以下三种
SEEK_SET 参数offset 即为新的读写位置。
SEEK_CUR 以目前的读写位置往后增加offset 个位移量。
SEEK_END 将读写位置指向文件尾后再增加offset 个位移。
注意:当whence 值为SEEK_CUR 或SEEK_END 时,,参数offet 允许负值的出现。
4.常见使用方式:
① 将读写位置移到文件开头时
lseek(int fildes, 0, SEEK_SET);
② 将读写位置移到文件尾时
lseek(int fildes, 0, SEEK_END);
③ 想要获取目前文件位置时
lseek(int fildes, 0, SEEK_CUR);