複製一個空洞檔案且忽略掉其空洞內容

來源:互聯網
上載者:User

標籤:des   style   blog   http   io   ar   color   os   sp   

原文:複製一個空洞檔案且忽略掉其空洞內容

  首先說一下什麼叫做空洞檔案!比如說,下面這段代碼:

 1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<errno.h> 5 #include<sys/types.h> 6 #include<sys/stat.h> 7 #include<fcntl.h> 8 #include<unistd.h> 9 10 #define MODE O_CREAT|O_RDWR|O_TRUNC11 int main(int argc,char *argv[])12 {13     int fd;14 15     if(argc != 2)16     {17     printf("Usage:%s <filename>\n",argv[0]);18     exit(EXIT_FAILURE);19     }20     if(-1 == (fd=open(argv[1],MODE,0644)))21     {22     printf("%s[open]%s\n",argv[0],strerror(errno));23     exit(EXIT_FAILURE);24     }25     if(-1 == write(fd,"abcde",5))26     {27     printf("%s[write]%s\n",argv[0],strerror(errno));28     exit(EXIT_FAILURE);29     }30     if(-1 == lseek(fd,5,SEEK_END))31     {32     printf("%s[lseek]%s\n",argv[0],strerror(errno));33     exit(EXIT_FAILURE);34     }35     if(-1 == write(fd,"ABCDE",5))36     {37     printf("%s[write]%s\n",argv[0],strerror(errno));38     exit(EXIT_FAILURE);39     }40     if(-1 == close(fd))41     {42     printf("%s[close]%s\n",argv[0],strerror(errno));43     exit(EXIT_FAILURE);44     }45     printf("空洞檔案已經建立成功!\n");46     return 0;47 }

 在這段代碼中,我首先在檔案中寫入abcde五個位元組的內容,然後在把檔案指標從檔案尾端向後移動5個位元組,再寫入ABCDE5個位元組的內容!這樣在這個檔案中,兩次abcde中間就會產生一個5個位元組空洞,這個空洞的內容都被寫成了0。檔案的空洞並不要求在磁碟上佔用儲存區,具體的處理方式和檔案系統的實現有關!我這個檔案如果用vim開啟的話會是這樣的效果!

中間藍色的^@就表示內容為0的空洞!

  接下來,我們再來談一談如何來複製一個空洞檔案,並且讓忽略掉它的空洞部分的內容!這裡我們就利用了空洞內容為0的這個特性!具體的實現方法就是通過查看讀出來的檔案內容的值是否為0,如果是則忽略,否則就儲存起來!具體的實現代碼如下:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<errno.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#define MODE O_RDWR#define SIZE 4096int main(int argc,char *argv[]){    if(argc != 3)    {    printf("Usage: %s source_file destination_file\n",argv[0]);    exit(EXIT_FAILURE);    }    int fd_s,fd_d;    //分別用來儲存讀出和寫入的檔案內容    char buf_r[SIZE],buf_w[SIZE];    //寫入緩衝指標的計數器    int w_l;    //read_length,write_length    //讀出和寫入的長度    int r_len,w_len;    if(-1 == (fd_s=open(argv[1],MODE)))    {      printf("%s[open]%s\n",argv[1],strerror(errno));      exit(EXIT_FAILURE);    }    if(-1 == (fd_d=open(argv[2],MODE|O_CREAT|O_TRUNC,0644)))    //如果目標檔案已經存在,則將其截短成0    {      printf("%s[open]%s\n",argv[2],strerror(errno));      exit(EXIT_FAILURE);    }    //如果檔案的內容過於龐大,我這裡是分批儲存的!且在《Unix環境進階編程》的3.9節已經論證過當SIZE為4096的時候I/O的效率最佳!    while((r_len=read(fd_s,buf_r,SIZE)) > 0)    {      w_l=0;      //將讀出內容中的非空洞內容賦值到buf_w中      for(int i=0;i<r_len;i++)      {          if(buf_r[i] != 0)          buf_w[w_l++]=buf_r[i];      }      //這裡得到的w_l表示的是字元數組的長度,注意數組是從0開始的      if(-1 == (w_len=write(fd_d,buf_w,w_l)))      {          printf("%s[write]%s\n",argv[0]+2,strerror(errno));          exit(EXIT_FAILURE);      }    }    if(-1 == close(fd_s))    {      printf("%s[close]%s\n",argv[1]+2,strerror(errno));      exit(EXIT_FAILURE);    }    if(-1 == close(fd_d))    {      printf("%s[close]%s\n",argv[2]+2,strerror(errno));      exit(EXIT_FAILURE);    }    return 0;}

  上面那個程式的思路就是每次讀取4096位元組,分批讀取源檔案的內容到buf_r中,然後檢查buf_r的內容,如果是0則忽略,否則就暫存到buf_w中,然後將其寫入到目標檔案中!

檢驗這個程式的運行結果我用了一個較大的空洞檔案,具體的運行結果如:

  

複製一個空洞檔案且忽略掉其空洞內容

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.