linux编程学习笔记(八) 文件 定位 lseek pread pwrite
2013-12-30 17:03
337 查看
原地址:http://blog.csdn.net/a8887396/article/details/9009411
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 例子
[cpp] viewplaincopy
#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);
}
[cpp] view
plaincopy
/*读取文件中的姓名
文件以结构体的形式写入
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),返回值都是当前位置
位置可以超出文件范围,只要不写入文件大小不会变化[cpp] view
plaincopy
#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超出文件范围,写入后文件大小会多出很多
[cpp] view
plaincopy
#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
[cpp] view
plaincopy
//读取文件中的姓名
#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 文件(虚拟内存 )
[cpp] view
plaincopy
#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); //没有改变 因为系统没有给写的权限
}
相关文章推荐
- Linux文件定位读写—lseek、pread、pwrite
- linux编程学习笔记(八) 文件 定位 lseek pread pwrite
- linux下如何通过lseek定位大文件
- lseek() 定位一个已经打开的文件
- 1.实验 5.2.5 文件定位 用lseek()函数实现以下功能 1. 获取文件大小 2. 为文件添加指定长度的空洞 3. 在指定位置写入指定内容 4. 读出指定位置的内容 1. 获取文件大小
- 多线程编程实例:不带缓冲的多线程文件复制 (使用pread pwrite版本)
- 重定位目标文件,链接
- javac 和 java 定位.class文件总结
- Windows定位窗口对应的exe文件
- Android Studio快速定位当前文件所在的位置
- android studio 快速定位文件
- GDB调试core文件样例(如何定位Segment fault) 【转】
- linux文件操作二(文件定位和状态函数)
- Android日志打印类LogUtils,能够定位到类名,方法名以及出现错误的行数并保存日志文件
- windows 7安装问题 无法定位到系统分区 + 展开文件时出现网络问题(错误代码:0x80070005)+ win8安装 找不到分区
- js调试-定位到函数所在文件位置
- Android Studio快速定位当前打开的文件在哪个目录(package)下
- elf文件类型四 Relocation (重定位)
- vc调试:使用MAP文件快速定位程序崩溃代码行
- C#导出到word文件,定位和字体控制和格式