文件打包源代码

来源:互联网 发布:数据库中注释 编辑:程序博客网 时间:2024/06/07 22:57

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#define MAXSIZE  300
/*记录文件的属性*/
struct record{
int type;         /*文件类型*/
int size;        /*文件大小*/
char filename[MAXSIZE]; /*文件路径名*/
};

/*打包函数
//path需要打包的文件夹路径
//fd打包文件的文件描述符,把待打包的文件写入fd对应的文件
*/
int list(char *path,int fd)
{
   DIR *dp; /*保存文件夹信息的结构体*/
   int i,count,len;
   int fd1;  /*保存读取的文件描述符*/
   struct dirent *dirp; /*保存从DIR结构体内读取的文件或者文件夹信息*/
   struct record file; /*自定义存储文件或文件夹的信息*/
   char buffer[MAXSIZE+1]; /*缓存*/ 
   if((dp = opendir(path)) == NULL)/*判断文件夹是否已经打开*/
       {
         perror("opendir");
         return 0; 
       }
 while((dirp = readdir(dp)) != NULL)/*从打开文件夹读取里面的子文件,或子文件夹*/
        {
         if(strcmp(dirp->d_name,".") !=0 && strcmp(dirp->d_name,"..") != 0)  /*如果读出的文件名为.或..则放弃*/
           {
            len = strlen(path);
            if(path[len-1] == '/')
                snprintf(file.filename,MAXSIZE-1,"%s%s",path,dirp->d_name);/*获得读取出的子文件(文件夹),的路径*/
            else
                snprintf(file.filename,MAXSIZE-1,"%s/%s",path,dirp->d_name);/*获得读取出的子文件(文件夹),的路径*/
           if(dirp->d_type == 4)/*d_type = 4 则说明这是文件夹*/
              { 
                 file.type = 4;
                 len = strlen(file.filename);
                 file.filename[len]  = '/';
                 file.filename[len+1] = 0;
                 printf("文件夹:%s/n",file.filename);
                 write(fd,&file,sizeof(file)); /*把文件夹的信息保存到打包的文件里面去*/
                 list(file.filename,fd); /*遍历这个文件夹*/
              }
            else if(dirp->d_type == 8) /*d_type = 8 表示普通文件*/
             {
                 if((fd1 = open(file.filename,O_RDONLY,0)) < 0) /*假如打开这个文件失败则读取下一个文件夹*/
                   continue;
                  int size = lseek(fd1,0,SEEK_END);/*获取文件的大小*/
                  file.size = size;
                  file.type = 8;
                  printf("文件:%s,大小%d/n",file.filename,file.size);
                  count =  write(fd,&file,sizeof(file));/*把文件的信息写入打包文件里面*/
                  lseek(fd1,0,SEEK_SET);/*把光标移动到文件起始出开始读*/
                  while((count = read(fd1,buffer,MAXSIZE)))/*读取文件内容,并写入打包文件里面*/
                     write(fd,buffer,count);
                  close(fd1);          /*文件读取完毕,关闭*/
             }
           } 
      }
}
/*给定一个文件路径创建相应的文件
//根据路径名判断最后一个字符是否为'/'
//假如给定的路径为chen/hellow 则创建hellow文件
//假如给定的路径为chen/hellow/ 则创建chen/hellow/ 这个路径相应的文件夹
*/
int creatfile(char *filePath)
{
  int len =  strlen(filePath);
  int i,flag;
  char file[MAXSIZE];
  for(i = 0; i < len ; i++)
   {
      if(filePath[i]=='/')
        {
          strncpy(file,filePath,i);
          file[i]=0; 
          mkdir(file,0777); 
          flag = i; 
        }     
   } 
  if(flag != (len -1))
    {
      printf("创建文件%s/n",filePath);
      return open(filePath,O_CREAT|O_RDWR,0777);
    }
  else
    {
       printf("创建文件夹%s/n",filePath);
       return 0;
    }
}
/*解压函数
//filePath待解压的文件路径
//name解压文件所保存的路径
*/
int extract(char *filePath,char *name)
{
   int src = open(filePath,O_RDONLY,0),des;/*打开待解压的文件*/
   struct record re;
   char buffer[MAXSIZE+1],*pstr;/*缓存*/
   int flag = 1,count,size = 0,i = 0;
   if(src < 0)
      {
        printf("打开文件失败/n");
        exit(0);
      }
    while(flag)/*flag=1则说明文件还没有解压完*/
      {
          if((count = read(src,&re,sizeof(re))))/*把信息读取到struct record 结构体*/
            {
               size = re.size;
               if(re.type == 4)/*假如是目录*/
                 {
                     i = 0;
                     while(re.filename[i] == '.'||re.filename[i] == '/')/* 使文件路径标准化如../hellow/变成hellow/ */
                           i++;
                     pstr = (re.filename+i);
                     snprintf(buffer,MAXSIZE,"%s/%s",name,pstr);/*把路经改成我门想要保存的路径*/
                     creatfile(buffer);/*创建相应的路径*/
                 }

 

 

               else if(re.type ==8) /*如果为普通文件*/
                 {
                   i = 0;
                   while(re.filename[i] == '.'||re.filename[i] == '/')
                           i++;
                   pstr = (re.filename+i);
                   snprintf(buffer,MAXSIZE,"%s/%s",name,pstr);
                   des = creatfile(buffer); /*创建相应的文件并返回文件描述符*/
                   while(size > 100)/*把内容写入刚创建的文件每次写入100个字节*/
                      {
                          read(src,buffer,100);
                          write(des,buffer,100);
                          size -= 100;  
                      }
                    if(size > 0)
                      {
                          read(src,buffer,size);
                          write(des,buffer,size);
                      }    
                  }
                else
                  {
                    printf("解压文件失败,格式不对或者文件已经破坏!/n");
                    exit(0);
                  }    
            }
          else
            {
               printf("解压完成!/n");  
               flag = 0;    
            }
      }
     return 0;     
}

 

 

int
main(int argc, char *argv[])
{
   int fd;
   char flag[10];
   char src[MAXSIZE],des[MAXSIZE];
   while(1)
     {
       printf("打包按1,解压按2,退出按3:/n");
       scanf("%s",flag);
       switch(flag[0])
         {
           case '1':
                {
                  printf("请输入需要压缩的文件夹路径:");
                  scanf("%s",src);
                  printf("请输入目标文件名:");
                  scanf("%s",des);
                  fd = open(des,O_CREAT|O_RDWR,0777);
                  if(fd < 0)
                     {
                        printf("目标文件名输入错误!/n");
                        break;
                     }
                  list(src,fd);
                   close(fd);
                  break;   
                }

 

           case '2':
                {
                   printf("请输入需要解压的文件夹路径:");
                   scanf("%s",src);
                   printf("请输入目标文件名:");
                   scanf("%s",des);
                   extract(src,des);
                   break;
                }
           case '3':{printf("byby/n");exit(0);}
           default:printf("%c不是命令/n",flag[0]);
          }         
     }
  return 0;
}