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

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

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

 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>\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 4096
int 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中,然后将其写入到目标文件中!

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

  

时间: 2024-09-17 04:42:56

复制一个空洞文件且忽略掉其空洞内容的相关文章

dnfEX怎么添加一个img文件到npk文件里

dnfex工具是所有喜欢修改模型的玩家的最爱,ex3.0中添加了新增img这个功能,很多玩家开始都弄不清楚这个功能怎么用. 其实这个功能真的很好很强大,我们可以利用这个功能把一套时装的img文件做成一个npk文件,这大大减少了我们改模型的工作量,那么怎么添加img文件呢,下面为大家带来的教程. EX3.0怎么添加img文件: 1.还没下ex3.0的亲可以用上面的地址下载,这个是绿色版的下载完毕不用安装直接使用. 这里以13年的五一萝莉套为例子.首先我们通过纸娃娃找到这套时装的所有img文件复制出

windows-复制一个500M文件到5个分区下算法问题

问题描述 复制一个500M文件到5个分区下算法问题 复制一个500M文件到5个分区下(比如在windows下将一个500M文件复制到c,e,d,e,f) 盘中,有什么好的效率高的思路 解决方案 对于机械硬盘,连续读写是最高效的,所以每次拷贝的分块要在32MB或者以上.针对机械硬盘,并发的写入反而慢,所以你的c d e f盘如果属于同一个硬盘,最好顺序依次拷贝而不是同时拷贝.操作系统有缓存的优化,所以不需要自己再特别处理. 解决方案二: copyfile不就行么..你想要多快完成复制?

java-Java 的 .class 文件里面的内容复制到另外一个TXT文件里面还能执行吗?

问题描述 Java 的 .class 文件里面的内容复制到另外一个TXT文件里面还能执行吗? 就是把 *.class文件里面的内容复制到一个文本文档里面,然后再把文件的后缀名改成.class,那么这个新的.class文件还可以运行吗? 解决方案 当然可以喽,运行的本来就是文件嘛,亲测没问题 解决方案二: 用的记事本喽,ansi 解决方案三: 测试过了,不可以.在EditPlus下以Hex viewer编码打开,将内容复制后保存成ANSI编码,文件就变大了.运行java命令报异常不兼容的默数值.理

lseek, fallocate来快速创建一个空洞文件,lseek不占用空间,fallocate占用空间(快速预分配)。

在开发过程中有时候需要为某个文件快速地分配固定大小的磁盘空间,为什么要这样做呢? (1)可以让文件尽可能的占用连续的磁盘扇区,减少后续写入和读取文件时的磁盘寻道开销: (2)迅速占用磁盘空间,防止使用过程中所需空间不足. (3)后面再追加数据的话,不会需要改变文件大小,所以后面将不涉及metadata的修改. 具体的例子有windows下的Bt下载服务,或者一些基于固定大小文件块的存储系统(如QFS). 为某个文件预分配磁盘空间必须是实际的占用磁盘空间, 以Linux来说,使用lseek或tru

我希望能复制一个文件件里的多张图片到另外一个文件夹用file.copy有问题

问题描述 我希望能复制一个文件件里的多张图片到另外一个文件夹用file.copy有问题 private void button1_Click(object sender, EventArgs e) { File.Copy(@"C:UsershjxDesktop33333",@"E:TESTJavaScriptTESTJavaScriptTESTima"); //FileInfo fi = new FileInfo(@"C:UsershjxDesktop33

编程- 悬赏20c币 vb用file控件获取一个文件并复制到指定文件夹

问题描述 悬赏20c币 vb用file控件获取一个文件并复制到指定文件夹 如题,用户使用时选取一个文件,然后自动复制到另一个已经指定好的文件夹,谢谢答的好的20c币 解决方案 求大神,求大神,谢谢谢谢谢 解决方案二: 用户选择好文件之后,点击确定,你在确定按钮的事件函数里使用filecopy函数直接复制文件http://baike.baidu.com/link?url=p0S_bFcHsJ1q8tk-CFCiaSGTak_K9xL0ZfjeEfmHM5K1PYrs9x0YwdI9cEvVFmfO

hadoop eclipse jar-Centos下怎么将一个jar文件复制到另一个jar文件中的lib目录中去

问题描述 Centos下怎么将一个jar文件复制到另一个jar文件中的lib目录中去 Eclipse配置Hadoop开发环境时,需要将Hadoop中的lib文件夹下的jar文件拷贝到,hadoop-eclipse-plugin-0.20.203.0.jar文件的lib目录下

IIS卸载后重装时提示:安装程序无法复制一个或多个文件 特定错误码是 0xe0000233_win服务器

IIS卸载后重装时提示: --------------------------- Windows 安装程序 --------------------------- 安装程序无法复制一个或多个文件.特定错误码是 0xe0000233.按"确定"以继续:或者按"取消",停止安装并且再试一次.如果继续,组件可能无法正常运行. --------------------------- 确定 取消 --------------------------- 网上找的解决办法都是说没

在应用程序根目录.自己定义一个WEB.CONFIG文件.会覆盖掉NET中的WEB.CONFIG吗?

问题描述 在应用程序根目录.自己定义一个WEB.CONFIG文件.会覆盖掉NET中的WEB.CONFIG吗?NET中的WEB.CONFIG里面有好多内容.要是自己定义了.覆盖掉的话.会影响应用程序的执行吗? 解决方案 解决方案二:不会覆盖但是每个程序只能有一个webconfig文件解决方案三:不会覆盖,最近的webconfig生效