要求:将多个文件打包到同一文件,然后进行解包,解包时如果文件名重复进行标号。
PS:这里只有打包功能,没有对大小进行压缩。
先考虑两个问题:
(1)解包时如何将不同文件分开?
我们可以在写入文件内容前,提前写入一个结构体,这个结构体存有文件的大小和文件名,这样在解包时,我们总是先读出一个结构体,得到下一个文件的大小和文件名,然后按照大小读出内容即可。
(2)如何判断文件名是否重复?
因为是C语言,没有map映射,所以手搓了一个哈希函数进行标记(但模数不是很大,打包文件较多容易冲突)。
一些细节的完善请自行实现。
打包程序如下:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <time.h> 5 #define USER_NAME_LEN 100 6 #define EMAIL_LEN 100 7 #define TIME_BUF_LEN 100 8 #define FILE_NAME_LEN 300 9 #define BUF_LEN 20 10 #define DWORD unsigned long 11 typedef struct FileStruct 12 { 13 char fileName[FILE_NAME_LEN]; 14 int fileSize; 15 } FileStruct; 16 char name[FILE_NAME_LEN]; 17 char buf[BUF_LEN]; 18 int getFileSize(char *fileName) 19 { 20 FILE* fp; 21 if((fp=fopen(fileName,"rb"))==NULL) 22 { 23 printf("文件打开失败!\n"); 24 return -1; 25 } 26 fseek(fp,0L,SEEK_END); 27 int s=ftell(fp); 28 fclose(fp); 29 return s; 30 } 31 int main(void) 32 { 33 FILE* dfile; 34 printf("输入目标文件名(含路径):"); 35 scanf("%s",name); 36 if((dfile=fopen(name,"wb"))==NULL) 37 { 38 printf("文件打开失败!\n"); 39 return 0; 40 } 41 int kase=0; 42 FILE* sfile; 43 while(1) 44 { 45 printf("输入要打包的#%d文件(含路径):",++kase); 46 scanf("%s",name); 47 if(strcmp(name,"exit")==0)break; 48 if((sfile=fopen(name,"rb"))==NULL) 49 { 50 printf("文件打开失败!\n"); 51 return 0; 52 } 53 FileStruct f; 54 f.fileSize=getFileSize(name); 55 if(f.fileSize==-1)return 0; 56 strcpy(f.fileName,strrchr(name,'\\')+1); 57 if(fwrite(&f,sizeof(FileStruct),1,dfile)!=1)printf("file write error!\n"); 58 int len=0; 59 while((len=fread(buf,1,BUF_LEN,sfile))>=BUF_LEN) 60 { 61 fwrite(buf,1,BUF_LEN,dfile); 62 } 63 fwrite(buf,1,len,dfile); 64 } 65 printf("打包结束!\n"); 66 fclose(dfile); 67 fclose(sfile); 68 getchar(); 69 getchar(); 70 return 0; 71 }
解包程序如下:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <time.h> 5 #define USER_NAME_LEN 100 6 #define EMAIL_LEN 100 7 #define TIME_BUF_LEN 100 8 #define FILE_NAME_LEN 300 9 #define BUF_LEN 20 10 #define DWORD unsigned long 11 #define ull unsigned long long 12 typedef struct FileStruct 13 { 14 char fileName[FILE_NAME_LEN]; 15 int fileSize; 16 } FileStruct; 17 FileStruct f; 18 char name[FILE_NAME_LEN]; 19 char buf[BUF_LEN],ans[BUF_LEN]; 20 char dic[FILE_NAME_LEN]; 21 int cnt[19260817]; 22 ull base=131,mod=19260817; 23 ull hashs(char* s) 24 { 25 int len=strlen(s); 26 ull ans=0; 27 for(int i=0;i<len;++i)ans=(ans*base+(ull)s[i])%mod; 28 return ans; 29 } 30 char* div(char* dname) 31 { 32 memset(ans,'\0',sizeof(ans)); 33 char* leave; 34 leave=strrchr(dname,'.'); 35 int i=0; 36 while(dname+i!=leave) 37 { 38 ans[i]=dname[i]; 39 ++i; 40 } 41 return ans; 42 } 43 int main(void) 44 { 45 printf("输入目标文件夹:"); 46 scanf("%s",dic); 47 printf("输入要解包的文件:"); 48 scanf("%s",name); 49 FILE* sfile; 50 FILE* dfile; 51 if((sfile=fopen(name,"rb"))==NULL) 52 { 53 printf("文件打开失败!\n"); 54 getchar(); 55 getchar(); 56 return 0; 57 } 58 while(fread(&f,sizeof(FileStruct),1,sfile)==1) 59 { 60 char temp[BUF_LEN],part[BUF_LEN]="(0)"; 61 strcpy(temp,dic); 62 strcat(temp,"\\"); 63 strcat(temp,div(f.fileName)); 64 ull res=hashs(f.fileName); 65 if(cnt[res]++) 66 { 67 part[1]+=cnt[res]; 68 strcat(temp,part); 69 } 70 strcat(temp,strrchr(f.fileName,'.')); 71 if((dfile=fopen(temp,"wb"))==NULL) 72 { 73 printf("文件解包失败!\n"); 74 getchar(); 75 getchar(); 76 return 0; 77 } 78 int left=f.fileSize; 79 while(left) 80 { 81 int Size=left>BUF_LEN?BUF_LEN:left; 82 fread(buf,Size,1,sfile); 83 fwrite(buf,Size,1,dfile); 84 left-=Size; 85 } 86 } 87 printf("解包结束!\n"); 88 fclose(sfile); 89 fclose(dfile); 90 getchar(); 91 getchar(); 92 return 0; 93 }