• 复制一个空洞文件且忽略掉其空洞内容


      首先说一下什么叫做空洞文件!比如说,下面这段代码:

     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_TRUNC
    11 int main(int argc,char *argv[])
    12 {
    13     int fd;
    14 
    15     if(argc != 2)
    16     {
    17     printf("Usage:%s <filename>
    ",argv[0]);
    18     exit(EXIT_FAILURE);
    19     }
    20     if(-1 == (fd=open(argv[1],MODE,0644)))
    21     {
    22     printf("%s[open]%s
    ",argv[0],strerror(errno));
    23     exit(EXIT_FAILURE);
    24     }
    25     if(-1 == write(fd,"abcde",5))
    26     {
    27     printf("%s[write]%s
    ",argv[0],strerror(errno));
    28     exit(EXIT_FAILURE);
    29     }
    30     if(-1 == lseek(fd,5,SEEK_END))
    31     {
    32     printf("%s[lseek]%s
    ",argv[0],strerror(errno));
    33     exit(EXIT_FAILURE);
    34     }
    35     if(-1 == write(fd,"ABCDE",5))
    36     {
    37     printf("%s[write]%s
    ",argv[0],strerror(errno));
    38     exit(EXIT_FAILURE);
    39     }
    40     if(-1 == close(fd))
    41     {
    42     printf("%s[close]%s
    ",argv[0],strerror(errno));
    43     exit(EXIT_FAILURE);
    44     }
    45     printf("空洞文件已经创建成功!
    ");
    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 4096
    int main(int argc,char *argv[])
    {
        if(argc != 3)
        {
        printf("Usage: %s source_file destination_file
    ",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
    ",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
    ",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
    ",argv[0]+2,strerror(errno));
              exit(EXIT_FAILURE);
          }
        }
        if(-1 == close(fd_s))
        {
          printf("%s[close]%s
    ",argv[1]+2,strerror(errno));
          exit(EXIT_FAILURE);
        }
        if(-1 == close(fd_d))
        {
          printf("%s[close]%s
    ",argv[2]+2,strerror(errno));
          exit(EXIT_FAILURE);
        }
    
        return 0;
    }

      上面那个程序的思路就是每次读取4096字节,分批读取源文件的内容到buf_r中,然后检查buf_r的内容,如果是0则忽略,否则就暂存到buf_w中,然后将其写入到目标文件中!

    检验这个程序的运行结果我用了一个较大的空洞文件,具体的运行结果如下图:

      

  • 相关阅读:
    hiveserver2 with kerberos authentication
    python Basic usage
    python Quicksort demo
    Python HeapSort
    mrunit for wordcount demo
    CCDH证书
    Hadoop question list
    Hadoop Yarn core concepts
    Hadoop Resource
    Hadoop could not find or load main class
  • 原文地址:https://www.cnblogs.com/bwangel23/p/4112364.html
Copyright © 2020-2023  润新知