linux编程学习笔记(八) 文件 定位 lseek pread pwrite
1IO的共享和效率read与write其中数据缓冲的大小建设设置为:getpagesize (一页的大小)或者40922 定位与读取数据(随机读取)read和write时自动移动读取位置lseek改变读取位置pread/pwrite在指定位置读写2.1lseek函数说明 off_t lseek(int fd, //文件描述符 off_t
·
1IO的共享和效率
read与write其中数据缓冲的大小建设设置为:getpagesize (一页的大小)或者4092
2 定位与读取数据(随机读取)
read和write时自动移动读取位置lseek改变读取位置
pread/pwrite在指定位置读写
2.1lseek函数说明
off_t lseek(int fd, //文件描述符
off_t offset,//偏移
int whence);//定位参数 开始SEEK_SET, 当前位置SEEK_CUR , 结束SEEK_END
返回值:当前读取在文件中的绝地位置
3 例子
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
//注意这里 为了以后读取方便 请人为对齐 不要让计算机来对齐
struct stu
{
int no;
char name[16];
float score;
};
int openfile(const char* filename)
{
int fd = open(filename,O_WRONLY|O_CREAT|O_EXCL,0666);
if(fd < 0)
{
perror("open error!");
}
return fd;
}
void input(struct stu *record)
{
printf("请输入学生ID:");
scanf("%d",&(record->no));
printf("请输入学生姓名:");
scanf("%s",record->name);
printf("请输入学生成绩:");
scanf("%f",&(record->score));
}
void save(int fd,struct stu* record)
{
write(fd,record,sizeof(struct stu));
}
int iscontinue()
{
char c;
printf("是否继续输入:y/n\n");
scanf("%c",&c);
scanf("%c",&c);
if(c == 'y')
{
return 1;
}
else
return 0;
}
int main()
{
int fd =openfile("stu.dat");
if(fd < 0)
{
return 1;
}
struct stu record;
while(1)
{
input(&record);
save(fd,&record);
if(! iscontinue() )
{
break;
}
}
close(fd);
}
/*读取文件中的姓名
文件以结构体的形式写入
struct stu
{
int no;
char name[16];
float score;
};
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
int main()
{
int fd = open("stu.dat",O_RDONLY);
if(fd < 0)
{
perror("open");
return 1;
}
int i = 0;
char buf[4092];
lseek(fd,i*24+4,SEEK_SET);
while(read(fd,buf,16))
{
printf("%s ",buf);
i++;
lseek(fd,i*24+4,SEEK_SET);
}
printf("\n");
close(fd);
}
4 lseek的定位位置超出文件大小时会发生什么?
1 lseek只要位置合法(绝对位置>=0),返回值都是当前位置
位置可以超出文件范围,只要不写入文件大小不会变化#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
int main()
{
int fd = open("dat",O_RDWR|O_CREAT,0666);
if(fd < 0)
{
perror("open");
return 1;
}
int r = lseek(fd,2000,SEEK_SET);
printf("%d\n",r);
close(fd);
}
zhao@ubuntu:~/unix/4$ ./lseek2
2000
zhao@ubuntu:~/unix/4$ ls -l dat
-rw-r--r-- 1 zhao zhao 0 2013-06-01 04:59 dat
lseek超出文件范围,写入后文件大小会多出很多
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
int main()
{
int fd = open("dat",O_RDWR|O_CREAT,0666);
if(fd < 0)
{
perror("open");
return 1;
}
int r = lseek(fd,2000,SEEK_SET);
printf("%d\n",r);
write(fd,"hello"5);
close(fd);
}
zhao@ubuntu:~/unix/4$ ls -l dat
-rw-r--r-- 1 zhao zhao 2005 2013-06-01 05:02 d
2 若是位置不合法 ,比如负数,返回-1
5 pread pwrite
函数描述#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset); //注意offset是绝对位置
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
pread=lseek+read
pwrite=lseek+write
返回值
读写的数据大小,出错返回-1
//读取文件中的姓名
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
int main()
{
int fd = open("stu.dat",O_RDONLY);
if(fd < 0)
{
perror("open");
return 1;
}
int i = 0;
char buf[4092];
while(pread(fd,buf,16,i*24+4))
{
printf("%s ",buf);
i++;
}
printf("\n");
close(fd);
}
pread pwrite会改变读写位置吗?
pread() reads up to count bytes from file descriptor fd at offset off‐
set (from the start of the file) into the buffer starting at buf. The
file offset is not changed.
pwrite() writes up to count bytes from the buffer starting at buf to
the file descriptor fd at offset offset. The file offset is not
changed.
记住 都不改变读写位置 , 这就是它们和lseek+read/write的区别
案例 读取/proc/$(pid)/mem 文件(虚拟内存 )
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
int a = 91119;
int main()
{
char filename[20];
memset(filename,0,20);
sprintf(filename,"/proc/%d/mem",getpid());
//mem文件 虚拟内存空间映射到mem上了
int fd = open(filename,O_RDWR);
if(fd < 0)
{
perror("open error");
return 1;
}
//读取&a这个位置的地址
int t;
pread(fd,&t,4,(off_t)&a);
printf("t:%d\n",t); //91119
t = 88888;
pwrite(fd,&t,4,(off_t)&a);//往所在a的地方写数据
printf("a=%d\n",a); //没有改变 因为系统没有给写的权限
}
更多推荐
已为社区贡献1条内容
所有评论(0)