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 例子

  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. }  


  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),返回值都是當前位置

位置可以超出文件範圍,只要不寫入文件大小不會變化
  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超出文件範圍,寫入後文件大小會多出很多
  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


  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 文件(虛擬內存 )


  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. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章