linux编程学习笔记(八) 文件 定位 lseek pread pwrite

原地址: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]  view plain copy
  1. #include <sys/types.h>  
  2.    #include <sys/stat.h>  
  3.  #include <fcntl.h>  
  4. #include <unistd.h>  
  5. #include <stdlib.h>  
  6. #include <stdio.h>  
  7. //注意这里 为了以后读取方便 请人为对齐 不要让计算机来对齐  
  8. struct stu  
  9. {  
  10.     int no;  
  11.     char name[16];  
  12.     float score;  
  13. };  
  14.   
  15. int openfile(const char* filename)  
  16. {  
  17.     int fd = open(filename,O_WRONLY|O_CREAT|O_EXCL,0666);  
  18.     if(fd < 0)  
  19.     {  
  20.         perror("open error!");  
  21.     }  
  22.       
  23.     return fd;  
  24. }  
  25.   
  26. void input(struct stu *record)  
  27. {  
  28.         printf("请输入学生ID:");  
  29.         scanf("%d",&(record->no));  
  30.         printf("请输入学生姓名:");  
  31.         scanf("%s",record->name);  
  32.         printf("请输入学生成绩:");  
  33.         scanf("%f",&(record->score));  
  34. }  
  35.   
  36. void save(int fd,struct stu* record)  
  37. {  
  38.     write(fd,record,sizeof(struct stu));  
  39. }  
  40.   
  41. int  iscontinue()  
  42. {  
  43.     char c;  
  44.     printf("是否继续输入:y/n\n");  
  45.     scanf("%c",&c);  
  46.     scanf("%c",&c);  
  47.     if(c == 'y')  
  48.     {  
  49.         return 1;  
  50.     }  
  51.     else  
  52.         return 0;  
  53. }  
  54.   
  55. int main()  
  56. {  
  57.       
  58.     int fd =openfile("stu.dat");  
  59.     if(fd < 0)  
  60.     {  
  61.         return 1;  
  62.     }  
  63.     struct stu  record;  
  64.     while(1)  
  65.     {  
  66.         input(&record);  
  67.         save(fd,&record);  
  68.   
  69.         if(! iscontinue() )  
  70.         {  
  71.             break;  
  72.         }  
  73.     }  
  74.     close(fd);  
  75. }  


[cpp]  view plain copy
  1. /*读取文件中的姓名 
  2. 文件以结构体的形式写入 
  3. struct stu 
  4. { 
  5.     int no; 
  6.     char name[16]; 
  7.     float score; 
  8. }; 
  9. */  
  10. #include <stdio.h>  
  11. #include <unistd.h>  
  12. #include <fcntl.h>  
  13. #include <sys/types.h>  
  14. int main()  
  15. {  
  16.     int fd = open("stu.dat",O_RDONLY);  
  17.     if(fd < 0)  
  18.     {  
  19.         perror("open");  
  20.         return 1;  
  21.     }  
  22.     int i = 0;  
  23.     char buf[4092];  
  24.     lseek(fd,i*24+4,SEEK_SET);   
  25.     while(read(fd,buf,16))  
  26.     {  
  27.         printf("%s ",buf);  
  28.         i++;  
  29.         lseek(fd,i*24+4,SEEK_SET);  
  30.     }  
  31.     printf("\n");  
  32.     close(fd);    
  33. }  

4  lseek的定位位置超出文件大小时会发生什么?

1 lseek只要位置合法(绝对位置>=0),返回值都是当前位置

位置可以超出文件范围,只要不写入文件大小不会变化
[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <fcntl.h>  
  4. #include <sys/types.h>  
  5. int main()  
  6. {  
  7.     int fd = open("dat",O_RDWR|O_CREAT,0666);  
  8.     if(fd < 0)  
  9.     {  
  10.         perror("open");  
  11.         return 1;  
  12.     }  
  13.     int r = lseek(fd,2000,SEEK_SET);  
  14.     printf("%d\n",r);  
  15.     close(fd);    
  16. }  



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 plain copy
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <fcntl.h>  
  4. #include <sys/types.h>  
  5. int main()  
  6. {  
  7.     int fd = open("dat",O_RDWR|O_CREAT,0666);  
  8.     if(fd < 0)  
  9.     {  
  10.         perror("open");  
  11.         return 1;  
  12.     }  
  13.     int r = lseek(fd,2000,SEEK_SET);  
  14.     printf("%d\n",r);  
  15.     write(fd,"hello"5);  
  16.     close(fd);    
  17. }  


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 plain copy
  1. //读取文件中的姓名    
  2. #include <stdio.h>  
  3. #include <unistd.h>  
  4. #include <fcntl.h>  
  5. #include <sys/types.h>  
  6.   
  7.   
  8. int main()  
  9. {  
  10.     int fd = open("stu.dat",O_RDONLY);  
  11.     if(fd < 0)  
  12.     {  
  13.         perror("open");  
  14.         return 1;  
  15.     }  
  16.     int i = 0;  
  17.     char buf[4092];  
  18.     while(pread(fd,buf,16,i*24+4))  
  19.     {  
  20.         printf("%s ",buf);  
  21.         i++;  
  22.     }  
  23.     printf("\n");  
  24.     close(fd);    
  25. }  



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 plain copy
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <fcntl.h>  
  4. #include <sys/types.h>  
  5. #include <string.h>  
  6.   
  7.   
  8. int a = 91119;  
  9. int main()  
  10. {  
  11.   
  12.   
  13.     char filename[20];  
  14.     memset(filename,0,20);  
  15.     sprintf(filename,"/proc/%d/mem",getpid());  
  16.     //mem文件 虚拟内存空间映射到mem上了  
  17.       
  18.       
  19.     int fd = open(filename,O_RDWR);  
  20.     if(fd < 0)  
  21.     {  
  22.         perror("open error");  
  23.         return 1;  
  24.     }  
  25.       
  26.     //读取&a这个位置的地址  
  27.     int t;  
  28.     pread(fd,&t,4,(off_t)&a);  
  29.     printf("t:%d\n",t); //91119  
  30.       
  31.       
  32.     t = 88888;  
  33.     pwrite(fd,&t,4,(off_t)&a);//往所在a的地方写数据  
  34.     printf("a=%d\n",a); //没有改变 因为系统没有给写的权限  
  35.       
  36. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux文件编程中,可以使用lseek函数来重置文件光标的位置。lseek函数的原型如下: ``` off_t lseek(int fd, off_t offset, int whence); ``` 其中,fd是文件描述符,用于标识打开的文件;offset是偏移量,用于指定光标相对于whence参数的偏移量;whence是参考位置,可以是以下值之一: - SEEK_SET:从文件起始位置开始计算偏移量。 - SEEK_CUR:从当前光标位置开始计算偏移量。 - SEEK_END:从文件末尾位置开始计算偏移量。 通过调用lseek函数,可以将文件光标重新定位到指定位置。在示例代码中,通过调用lseek(fd,0,SEEK_SET)将文件光标重置到文件起始位置。这样就可以在重置光标后从指定位置继续读取文件内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Linux文件编程之标准C库](https://blog.csdn.net/weixin_45637109/article/details/129930976)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Linux系统编程文件篇](https://blog.csdn.net/woweiwang007/article/details/129160046)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值