gz文件是gzip产生的压缩文件。前几天接到一个小任务,说是要将其中被压缩的数据提取出来。于是动手写了个小程序实现之。
关于gzip文件格式的相关信息,可以查看RFC 1952
代码如下:
#include
#include
#include
#include
int main(int argc,char* argv[])
{
FILE* sfp=NULL;
FILE* dfp=NULL;
int readnum;
int count=0; /*for tail cross two bufs*/
unsigned char uc_magic;
unsigned char uc_temp;
int FLG_FEXTRA_SET=0;
int FLG_FNAME_SET=0;
int FLG_FCOMMENT_SET=0;
int FLG_FHCRC_SET=0;
unsigned int xlen=0;
unsigned char buf[4096]="";
unsigned char buf2[4096]="";
unsigned char result[4096]="";
if(argc<2)
{
printf("usage main your gz file\n");
return(0);
}
sfp=fopen(argv[1],"rb");
if(sfp==NULL)
{
printf("open file error! errmsg:%s\n",strerror(errno));
return(0);
}
dfp=fopen("result","wb+");
/*check file magic number*/
uc_magic=fgetc(sfp);
if(uc_magic!=0x1f)
{
printf("error this is not a gz file!\n");
fclose(sfp);
fclose(dfp);
return(0);
}
uc_magic=fgetc(sfp);
if(uc_magic!=0x8b)
{
printf("error this is not a gz file!\n");
fclose(sfp);
fclose(dfp);
return(0);
}
/*ignore the CM byte*/
fseek(sfp,1,SEEK_CUR);
/*read FLG*/
uc_temp=fgetc(sfp);
if(uc_temp==EOF)
{
printf("end of file when read FLG\n");
fclose(sfp);
fclose(dfp);
return(0);
}
/*check FLG.FEXTRA*/
if(uc_temp&0x04)
{
FLG_FEXTRA_SET=1;
}
/*check FLG.FNAME*/
if(uc_temp&0x08)
{
FLG_FNAME_SET=1;
}
/*check FLG.FCOMMENT*/
if(uc_temp&0x10)
{
FLG_FCOMMENT_SET=1;
}
/*skip MIME 4 bytes,skip XFL 1 byte, skip OS 1 byte */
fseek(sfp,6,SEEK_CUR);
/*FLG.FEXTRA is seted */
if(FLG_FEXTRA_SET)
{
/*skip s1 and s2 read XLEN,and skip XLEN byte*/
fseek(sfp,2,SEEK_CUR);
fread(&xlen,2,1,sfp);
fseek(sfp,xlen,SEEK_CUR);
}
/*FLG.FNAME is seted*/
if(FLG_FNAME_SET)
{
/*ignore file name,read until 0 occur*/
while(fgetc(sfp));
}
/*FLG.FCOMMENT is seted*/
if(FLG_FCOMMENT_SET)
{
/*ignore comments,read until 0 occur*/
while(fgetc(sfp));
}
/*FLG.FHCRC is seted*/
if(FLG_FHCRC_SET)
{
fseek(sfp,2,SEEK_CUR);
}
/*fread return 0 when content length is not engouh*/
while((readnum=fread(buf,1,4096,sfp))!=0)
{
if(feof(sfp))
{
/* EOF cut CRC32 and ISIZE 8 bytes*/
/* be care when the tail cross two buf~~~~*/
if(readnum<8)
{
/* tail does cross two buf~~hell!!*/
memcpy(buf,buf2,count-(8-readnum));
memcpy(result,buf,count-(8-readnum));
fwrite(result,count-(8-readnum),1,dfp);
break;
}
else
{
if(count!=0)
{
memcpy(result,buf2,count);
fwrite(result,count,1,dfp);
}
memcpy(result,buf,readnum-8);
fwrite(result,readnum-8,1,dfp);
break;
}
}
else
{
if(count!=0)
{
memcpy(result,buf2,count);
fwrite(result,count,1,dfp);
memcpy(buf2,buf,readnum);
count=readnum;
}
else
{
memcpy(buf2,buf,readnum);
count=readnum;
}
}
}
fclose(sfp);
fflush(dfp);
fclose(dfp);
return(0);
}