用C实现的一个huffman压缩解压缩程序

#include  < stdio.h >
#include 
< stdlib.h >
#include 
< string .h >
#include 
< assert.h >
#include 
< limits.h >

#include 
< time.h >

#define  SUCCEEDED    0
#define  FAILED        1

typedef unsigned 
int  UINT;
typedef unsigned 
char  UCHAR;
typedef unsigned 
short  USHORT;

#define  UINT_SIZE sizeof(UINT)
#define  UCHAR_SIZE sizeof(UCHAR)
#define  USHORT_SIZE sizeof(USHORT)

#define  CODE_SIZE 256
#define  ZIP_HEAD_FLAG 0xaaaaaaaa /* 10间隔 作为文件头 */

struct  _HuffmanTreeNode
{
    UINT  freq; 
/* 频度 */
    UCHAR data;
    
struct _HuffmanTreeNode *leftChild;
    
struct _HuffmanTreeNode *rightChild;
}
;

struct  _DataCode
{
    USHORT len;
    UCHAR  
*pCode;
}
;

struct  _Code2Data
{
    USHORT len;
    UCHAR 
*pCode;
    UCHAR data;
}
;

typedef 
struct  _HuffmanTreeNode HuffmanTreeNode;
typedef 
struct  _DataCode DataCode;
typedef 
struct  _Code2Data Code2Data;

UCHAR ConvertToCodeData(
const  UCHAR codeStr[CHAR_BIT]);
void  ConvertToCodeStr(UCHAR codeData, UCHAR codeStr[CHAR_BIT]);

/************************************************************************/
/*                   Huffman树相关函数                                  */
/************************************************************************/
void  GetDataFreq(FILE  * fp, UINT freqArr[CODE_SIZE])
{
    UCHAR buffer;

    fseek(fp, 
0L, SEEK_SET); /* 将文件指针重新定位到起始位置 */
    memset(freqArr, 
0, UINT_SIZE * CODE_SIZE);
    
while(!feof(fp)) {
        fread(
&buffer, UCHAR_SIZE, 1, fp);
        
++freqArr[buffer];
    }

}


void  SwapVoidPnt( void   ** vpnt1,  void   ** vpnt2)
{
    
void *tempPnt = *vpnt1;
    
*vpnt1 = *vpnt2;
    
*vpnt2 = tempPnt;
}


void  BuildHuffmanTree(HuffmanTreeNode  ** pTreeHead,  const  UINT freqArr[CODE_SIZE])
{
    HuffmanTreeNode 
**dataFreqArr;
    HuffmanTreeNode 
*tempInsertTreeNode;
    UINT freqLen 
= CODE_SIZE;
    
int i;

    dataFreqArr 
= (HuffmanTreeNode **)malloc(sizeof(HuffmanTreeNode** freqLen);
    
for(i = 0; i < CODE_SIZE; ++i) {
        dataFreqArr[i] 
= (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode));
        dataFreqArr[i]
->data = (UCHAR)i;
        dataFreqArr[i]
->freq = freqArr[i];
        dataFreqArr[i]
->leftChild = NULL;
        dataFreqArr[i]
->rightChild = NULL;
    }


    
while(freqLen != 1{
        
/* 把频度最小的两个移到最后两位 并且最后的小于最后第二个 */
        
if(dataFreqArr[freqLen-1]->freq > dataFreqArr[freqLen-2]->freq)
            SwapVoidPnt(dataFreqArr 
+ freqLen-1, dataFreqArr + freqLen-2);
        
for(i = freqLen-2-1; i >= 0--i) {
            
if(dataFreqArr[freqLen-1]->freq > dataFreqArr[i]->freq) {
                SwapVoidPnt(dataFreqArr 
+ freqLen-2, dataFreqArr + i);
                SwapVoidPnt(dataFreqArr 
+ freqLen-1, dataFreqArr + freqLen-2);
            }
 else if(dataFreqArr[freqLen-2]->freq > dataFreqArr[i]->freq) {
                SwapVoidPnt(dataFreqArr 
+ freqLen-2, dataFreqArr + i);
            }

        }

        
/* 合并最后两个 */
        tempInsertTreeNode 
= (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode));
        tempInsertTreeNode
->freq = dataFreqArr[freqLen-1]->freq + dataFreqArr[freqLen-2]->freq;
        tempInsertTreeNode
->leftChild = dataFreqArr[freqLen-1];
        tempInsertTreeNode
->rightChild = dataFreqArr[freqLen-2];
        dataFreqArr[freqLen
-2= tempInsertTreeNode;
        
--freqLen;
    }


    
*pTreeHead = dataFreqArr[0];
    free(dataFreqArr); 
/* 只是存放节点用的 离开之前应释放 */
}


int  CmpCode2Data( const   void   * op1,  const   void   * op2)
{
    UINT minLen 
= ((DataCode*)op1)->len < ((DataCode*)op2)->len ? ((DataCode*)op1)->len : ((DataCode*)op2)->len;
    UINT i;

    
for(i = 0; i < minLen; ++i) {
        
if(((DataCode*)op1)->pCode[i] != ((DataCode*)op2)->pCode[i])
            
return ((DataCode*)op1)->pCode[i] - ((DataCode*)op2)->pCode[i];
    }

    
if(((DataCode*)op1)->len == ((DataCode*)op2)->len)
        
return 0;
    
if(((DataCode*)op1)->len < ((DataCode*)op2)->len)
        
return -((DataCode*)op2)->pCode[i];
    
return ((DataCode*)op1)->pCode[i];
}


void  RebuildHuffmanTreeOrder(HuffmanTreeNode  ** pTreeHead, UINT start, UINT end,
                             UINT deep, 
const  Code2Data code2DataArr[CODE_SIZE])
{
    UINT mid, i;
    HuffmanTreeNode 
*insertChild = NULL;

    assert(start 
< end);
    assert(deep 
< CODE_SIZE);

    
/* 根据当前层是0还是1 把数组分成两部分 */
    mid 
= end;
    
for(i = start; i < end; ++i) {
        assert(code2DataArr[i].len 
> deep);
        
if(code2DataArr[i].pCode[deep] != 0{
            mid 
= i;
            
break;
        }

    }


    
if(*pTreeHead == NULL) {
        
*pTreeHead = (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode));
        
//assert(*pTreeHead);
        (*pTreeHead)->leftChild = NULL;
        (
*pTreeHead)->rightChild = NULL;
    }

    
/* 不能在这里插数据 即使只有一个 也不能将其作为头节点 必须通过头节点连至他 他也是有编码的 就是0 */
    
/*if(start == end-1) {
        (*pTreeHead)->leftChild = NULL;
        (*pTreeHead)->rightChild = NULL;
        (*pTreeHead)->data = code2DataArr[start].data;
        return ;
    }
*/

    
    
/* 当前层是0的部分 */
    
if(mid-1 == start) {
        insertChild 
= (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode));
        insertChild
->leftChild = NULL;
        insertChild
->rightChild = NULL;
        insertChild
->data = code2DataArr[mid - 1].data;
        (
*pTreeHead)->leftChild = insertChild;
    }
 else
        RebuildHuffmanTreeOrder(
&(*pTreeHead)->leftChild, start, mid, deep+1, code2DataArr);

    
/* 当前层是1的部分 */
    
if(mid == end-1{
        insertChild 
= (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode));
        insertChild
->leftChild = NULL;
        insertChild
->rightChild = NULL;
        insertChild
->data = code2DataArr[mid].data;
        (
*pTreeHead)->rightChild = insertChild;
    }
else
        RebuildHuffmanTreeOrder(
&(*pTreeHead)->rightChild, mid, end, deep+1, code2DataArr);
}


void  RebuildHuffmanTree(HuffmanTreeNode  ** pTreeHead,  const  DataCode dataCodeArr[CODE_SIZE])
{
    Code2Data code2DataArr[CODE_SIZE];
    UINT i;

    
for(i = 0; i < CODE_SIZE; ++i) {
        code2DataArr[i].data 
= i;
        code2DataArr[i].len 
= dataCodeArr[i].len;
        code2DataArr[i].pCode 
= dataCodeArr[i].pCode;
    }

    qsort(code2DataArr, CODE_SIZE, 
sizeof(Code2Data), CmpCode2Data);
    RebuildHuffmanTreeOrder(pTreeHead, 
0, CODE_SIZE, 0, code2DataArr);
    
/* 不对code2DataArr中的指针进行释放 因为code2DataArr中的指针是来自dataCodeArr中的 */
}


void  DeleteHuffmanTree(HuffmanTreeNode  ** pTreeHead)
{
    
if(*pTreeHead != NULL) {
        
if((*pTreeHead)->leftChild != NULL)
            DeleteHuffmanTree(
&((*pTreeHead)->leftChild));
        
if((*pTreeHead)->rightChild != NULL)
            DeleteHuffmanTree(
&((*pTreeHead)->rightChild));
        free(
*pTreeHead);
        
*pTreeHead = NULL;
    }

}


void  GetHuffmanCode( const  HuffmanTreeNode  * pTreeHead, UCHAR code[CODE_SIZE], 
                    USHORT codeLen, DataCode dataCodeArr[CODE_SIZE])
{
    
if(pTreeHead != NULL) {
        
if(pTreeHead->leftChild != NULL) {
            code[codeLen] 
= 0;
            GetHuffmanCode(pTreeHead
->leftChild, code, codeLen+1, dataCodeArr);
            assert(pTreeHead
->rightChild != NULL); /* 不可能出现一边有孩子节点 一边又没有的情况 */
            code[codeLen] 
= 1;
            GetHuffmanCode(pTreeHead
->rightChild, code, codeLen+1, dataCodeArr);
        }
 else /* 叶子节点 */
            dataCodeArr[pTreeHead
->data].pCode = (UCHAR *)malloc(UCHAR_SIZE * codeLen);
            memcpy(dataCodeArr[pTreeHead
->data].pCode, code, UCHAR_SIZE * codeLen);
            dataCodeArr[pTreeHead
->data].len  = codeLen;
        }

    }

}


void  GetFileHuffmanCode(FILE  * fp, DataCode dataCodeArr[CODE_SIZE])
{
    HuffmanTreeNode 
*pTreeHead = NULL;
    UINT freqArr[
256];
    UCHAR code[CODE_SIZE];

    GetDataFreq(fp, freqArr);
    BuildHuffmanTree(
&pTreeHead, freqArr);
    memset(dataCodeArr, 
0sizeof(DataCode) * CODE_SIZE);
    memset(code, 
0, UCHAR_SIZE * CODE_SIZE);
    GetHuffmanCode(pTreeHead, code, 
0, dataCodeArr);
    DeleteHuffmanTree(
&pTreeHead);
}


/************************************************************************/
/*                  压缩 解压缩的相关文件操作函数                       */
/************************************************************************/

/* 头存的是字符和编码对应的表 存频度 再重新构造huffman树会有问题 因为有可能存在频度相同的 */
int  ReadZipFileHead(FILE  * fp, DataCode dataCodeArr[CODE_SIZE])
{
    UINT zipHeadFlag;
    USHORT codeLen, i, j;
    UCHAR codeBuffer, data;
    UCHAR codeStr[CHAR_BIT];

    fseek(fp, 
0L, SEEK_SET);
    fread(
&zipHeadFlag, UINT_SIZE, 1, fp);
    
if(zipHeadFlag != ZIP_HEAD_FLAG)
        
return FAILED;

    memset(dataCodeArr, 
0sizeof(DataCode) * CODE_SIZE);
    
for(i = 0; i < CODE_SIZE; ++i) {
        fread(
&data, UCHAR_SIZE, 1, fp);
        assert(data 
== i);
        fread(
&codeLen, USHORT_SIZE, 1, fp);
        dataCodeArr[data].len  
= codeLen;
        
/* 把编码还原成字符串 */
        assert(dataCodeArr[data].pCode 
== NULL);
        dataCodeArr[data].pCode 
= (UCHAR *)malloc(UCHAR_SIZE * codeLen);
        
for(j = 0; j < codeLen - codeLen % CHAR_BIT; j += CHAR_BIT) {
            fread(
&codeBuffer, UCHAR_SIZE, 1, fp);
            ConvertToCodeStr(codeBuffer, codeStr);
            memcpy(dataCodeArr[data].pCode 
+ j, codeStr, UCHAR_SIZE * CHAR_BIT);
        }

        
if(codeLen % CHAR_BIT != 0{
            fread(
&codeBuffer, UCHAR_SIZE, 1, fp);
            ConvertToCodeStr(codeBuffer, codeStr);
            memcpy(dataCodeArr[data].pCode 
+ j, codeStr, UCHAR_SIZE * (codeLen % CHAR_BIT));
        }

    }

    
return SUCCEEDED;
}


void  WriteZipFileHead(FILE  * fp,  const  DataCode dataCodeArr[CODE_SIZE])
{
    USHORT i, j;
    UCHAR codeBuffer, codeStr[CHAR_BIT];
    UINT zipHeadFlag 
= ZIP_HEAD_FLAG;

    fseek(fp, 
0L, SEEK_SET);
    fwrite(
&zipHeadFlag, UINT_SIZE, 1, fp);
    
for(i = 0; i < CODE_SIZE; ++i) {
        fwrite(
&i, UCHAR_SIZE, 1, fp);
        fwrite(
&dataCodeArr[i].len, USHORT_SIZE, 1, fp);
        
/* 将编码字符串合成字节码写入 */
        
for(j = 0; j < dataCodeArr[i].len - dataCodeArr[i].len % CHAR_BIT; j += CHAR_BIT) {
            memcpy(codeStr, dataCodeArr[i].pCode 
+ j, UCHAR_SIZE * CHAR_BIT);
            codeBuffer 
= ConvertToCodeData(codeStr);
            fwrite(
&codeBuffer, UCHAR_SIZE, 1, fp);
        }

        
if(dataCodeArr[i].len % CHAR_BIT != 0{
            memcpy(codeStr, dataCodeArr[i].pCode 
+ j, UCHAR_SIZE * (dataCodeArr[i].len % CHAR_BIT));
            codeBuffer 
= ConvertToCodeData(codeStr);
            fwrite(
&codeBuffer, UCHAR_SIZE, 1, fp);
        }

    }

}


UCHAR ConvertToCodeData(
const  UCHAR codeStr[CHAR_BIT])
{
    UCHAR retCode 
= 0;
    
int i;
    
    
for(i = CHAR_BIT-1; i >= 0--i) {
        retCode 
<<= 1;
        
if(codeStr[i] != 0)
            retCode 
|= 1;
    }

    
return retCode;
}


void  ConvertToCodeStr(UCHAR codeData, UCHAR codeStr[CHAR_BIT])
{
    UINT i;

    
for(i = 0; i < CHAR_BIT; ++i) {
        codeStr[i] 
= ((codeData & 1!= 0);
        codeData 
>>= 1;
    }

}


int  ZipFile( const   char   * sourceFileName,  const   char   * targetFileName)
{
    FILE 
*sourceFp = NULL, *targetFp = NULL;
    DataCode dataCodeArr[CODE_SIZE];
    USHORT writeCodeLen, i;
    UCHAR writeCode[CHAR_BIT], readData, writeData, lastBtyeLen;
    fpos_t lastBtyePos;

    
if((sourceFp = fopen(sourceFileName, "rb")) == NULL) {
        printf(
"打开%s文件错误! ", sourceFileName);
        
return FAILED;
    }

    
if((targetFp = fopen(targetFileName, "w+b")) == NULL) {
        printf(
"打开%s文件错误! ", targetFileName);
        fclose(sourceFp);
        
return FAILED;
    }

    GetFileHuffmanCode(sourceFp, dataCodeArr);
    WriteZipFileHead(targetFp, dataCodeArr);
    lastBtyeLen 
= 0;
    fgetpos(targetFp, 
&lastBtyePos); /* 记录位子 后面得到长度信息后 再在这里写 */
    fwrite(
&lastBtyeLen, UCHAR_SIZE, 1, targetFp);

    
/* 对源数据进行编码转换 并写入目标文件中 */
    memset(writeCode, 
0, CHAR_BIT);
    writeCodeLen 
= 0;
    fseek(sourceFp, 
0L, SEEK_SET);
    
while(!feof(sourceFp)) {
        fread(
&readData, UCHAR_SIZE, 1, sourceFp);
        
for(i = 0; i < dataCodeArr[readData].len; ++i) {
            writeCode[writeCodeLen
++= dataCodeArr[readData].pCode[i];
            
if(writeCodeLen >= CHAR_BIT) {
                writeData 
= ConvertToCodeData(writeCode);
                fwrite(
&writeData, UCHAR_SIZE, 1, targetFp);
                memset(writeCode, 
0, UCHAR_SIZE * CHAR_BIT);
                writeCodeLen 
= 0;
            }

        }

    }

    
/* 把剩余的写入文件 */
    
if(writeCodeLen != 0{
        writeData 
= ConvertToCodeData(writeCode);
        fwrite(
&writeData, UCHAR_SIZE, 1, targetFp);
    }

    lastBtyeLen 
= writeCodeLen;
    fsetpos(targetFp, 
&lastBtyePos);
    fwrite(
&lastBtyeLen, UCHAR_SIZE, 1, targetFp);

    
/* 清理 */
    
for(i = 0; i < CODE_SIZE; ++i) {
        
if(dataCodeArr[i].pCode != NULL) {
            free(dataCodeArr[i].pCode);
            dataCodeArr[i].pCode 
= NULL;
        }

    }

    fclose(sourceFp);
    fclose(targetFp);
    
return SUCCEEDED;
}


int  UnzipFile( const   char   * sourceFileName,  const   char   * targetFileName)
{
    FILE 
*sourceFp = NULL, *targetFp = NULL;
    DataCode dataCodeArr[CODE_SIZE];
    HuffmanTreeNode 
*pTreeHead = NULL, *pTreeNode = NULL;
    UCHAR codeStream[CODE_SIZE], codeStr[CHAR_BIT], readData, writeData, lastBtyeLen;
    
int codeStreamLen, i;

    
if((sourceFp = fopen(sourceFileName, "rb")) == NULL) {
        printf(
"打开%s文件错误! ", sourceFileName);
        
return FAILED;
    }

    
if((targetFp = fopen(targetFileName, "w+b")) == NULL) {
        printf(
"打开%s文件错误! ", targetFileName);
        fclose(sourceFp);
        
return FAILED;
    }


    ReadZipFileHead(sourceFp, dataCodeArr);
    fread(
&lastBtyeLen,UCHAR_SIZE, 1, sourceFp);
    RebuildHuffmanTree(
&pTreeHead, dataCodeArr);
    codeStreamLen 
= 0;
    
while(!feof(sourceFp) || codeStreamLen > 0{
        
while(!feof(sourceFp) && codeStreamLen < CODE_SIZE - CHAR_BIT) {
            fread(
&readData, UCHAR_SIZE, 1, sourceFp);
            ConvertToCodeStr(readData, codeStr);
            memcpy(codeStream
+codeStreamLen, codeStr, CHAR_BIT);
            codeStreamLen 
+= CHAR_BIT;
            
if(feof(sourceFp))
                codeStreamLen 
-= lastBtyeLen + CHAR_BIT; /* 咋就多出一字节 纳闷 */
        }


        
/* 通过编码查找原数据 */
        pTreeNode 
= pTreeHead;
        
for(i = 0; i < codeStreamLen; ++i) {
            
if(codeStream[i] == 0{
                pTreeNode 
= pTreeNode->leftChild;
                
if(pTreeNode->leftChild == NULL)
                    
break;
            }
 else {
                pTreeNode 
= pTreeNode->rightChild;
                
if(pTreeNode->leftChild == NULL)
                    
break;
            }

        }

        assert(pTreeNode
->rightChild == NULL); /* 是一个数据节点 左右子节点肯定都为空 */
        writeData 
= pTreeNode->data;
        fwrite(
&writeData, UCHAR_SIZE, 1, targetFp);

        
/* 把读取过的去掉 */
        codeStreamLen 
-= i + 1;
        memcpy(codeStream, codeStream
+i+1, codeStreamLen);
    }


    
/* 清理 */
    DeleteHuffmanTree(
&pTreeHead);
    
for(i = 0; i < CODE_SIZE; ++i) {
        
if(dataCodeArr[i].pCode != NULL) {
            free(dataCodeArr[i].pCode);
            dataCodeArr[i].pCode 
= NULL;
        }

    }

    fclose(sourceFp);
    fclose(targetFp);
    
return SUCCEEDED;
}


/************************************************************************/
/*                           测试代码                                   */
/************************************************************************/

void  TestCreateTestFile( const   char   * fileName)
{
    FILE 
*fp = NULL;
    UINT i;

    
if((fp = fopen(fileName, "w+b")) == NULL) {
        printf(
"打开%s文件失败! ", fileName);
        
return ;
    }

    
for(i = 0; i < 45++i)
        fputc(
'a', fp);
    
for(i = 0; i < 13++i)
        fputc(
'b', fp);
    
for(i = 0; i < 12++i)
        fputc(
'c', fp);
    
for(i = 0; i < 16++i)
        fputc(
'd', fp);
    
for(i = 0; i < 9++i)
        fputc(
'e', fp);
    
for(i = 0; i < 5++i)
        fputc(
'f', fp);
    fclose(fp);
}


void  Test_GetDataFreq( void )
{
    UINT freqArr[CODE_SIZE];
    FILE 
*fp = NULL;

    fp 
= fopen("Test.txt""rb");
    assert(fp 
!= NULL);
    GetDataFreq(fp, freqArr);
    assert(freqArr[
'a'= 45);
    assert(freqArr[
'b'= 13);
    assert(freqArr[
'c'= 12);
    assert(freqArr[
'd'= 16);
    assert(freqArr[
'e'= 9);
    assert(freqArr[
'f'= 5);
    fclose(fp);
}


void  Test_BuildHuffmanTree( void )
{
    UINT freqArr[CODE_SIZE];
    HuffmanTreeNode 
*pTreeHead = NULL, *pTreeNode = NULL;

    
/*memset(freqArr, 0, UINT_SIZE * CODE_SIZE);
    freqArr['a'] = 45;
    freqArr['b'] = 13;
    freqArr['c'] = 12;
    freqArr['d'] = 16;
    freqArr['e'] = 9;
    freqArr['f'] = 5;
*/

    FILE 
*fp = NULL;
    fp 
= fopen("Test.txt""rb");
    assert(fp 
!= NULL);
    GetDataFreq(fp, freqArr);
    fclose(fp);

    BuildHuffmanTree(
&pTreeHead, freqArr);
    pTreeNode 
= pTreeHead;
    assert(pTreeNode
->leftChild->data == 'a');
    pTreeNode 
= pTreeNode->rightChild;
    assert(pTreeNode
->leftChild->leftChild->data == 'c');
    assert(pTreeNode
->leftChild->rightChild->data == 'b');
    pTreeNode 
= pTreeNode->rightChild;
    assert(pTreeNode
->rightChild->data == 'd');
    pTreeNode 
= pTreeNode->leftChild;
    assert(pTreeNode
->leftChild->rightChild->data == 'f');
    assert(pTreeNode
->rightChild->data == 'e');
    DeleteHuffmanTree(
&pTreeHead);
}


void  TestNormalStr2CodeStr( const   char   * normalStr, UCHAR codeStr[CODE_SIZE], USHORT  * codeLen)
{
    USHORT i;

    
*codeLen = (USHORT)strlen(normalStr);
    
for(i = 0; i < *codeLen; ++i)
        codeStr[i] 
= (normalStr[i] == '1');
}


void  Test_GetFileHuffmanCode( void )
{
    DataCode dataCodeArr[CODE_SIZE];
    FILE 
*fp = NULL;
    UCHAR codeStr[CODE_SIZE];
    USHORT codeLen, i;

    fp 
= fopen("Test.txt""rb");
    assert(fp 
!= NULL);
    GetFileHuffmanCode(fp, dataCodeArr);
    fclose(fp);

    TestNormalStr2CodeStr(
"0", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'a'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"101", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'b'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"100", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'c'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"111", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'd'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"1101", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'e'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"11001", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'f'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);

    
for(i = 0; i < CODE_SIZE; ++i) {
        
if(dataCodeArr[i].pCode != NULL) {
            free(dataCodeArr[i].pCode);
            dataCodeArr[i].pCode 
= NULL;
        }

    }

}


void  Test_ReadWriteZipFileHead( void )
{
    DataCode dataCodeArr[CODE_SIZE];
    FILE 
*fp = NULL;
    UCHAR codeStr[CODE_SIZE];
    USHORT codeLen, i;

    fp 
= fopen("Test.txt""rb");
    assert(fp 
!= NULL);
    GetFileHuffmanCode(fp, dataCodeArr);
    fclose(fp);

    fp 
= fopen("Test_ZipFileHead.txt""w+b");
    assert(fp 
!= NULL);
    WriteZipFileHead(fp, dataCodeArr);

    
for(i = 0; i < CODE_SIZE; ++i) {
        
if(dataCodeArr[i].pCode != NULL) {
            free(dataCodeArr[i].pCode);
            dataCodeArr[i].pCode 
= NULL;
        }

    }

    memset(dataCodeArr, 
0sizeof(DataCode) * CODE_SIZE);

    fseek(fp, 
0L, SEEK_SET);
    assert(fp 
!= NULL);
    ReadZipFileHead(fp, dataCodeArr);
    fclose(fp);

    TestNormalStr2CodeStr(
"0", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'a'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"101", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'b'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"100", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'c'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"111", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'd'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"1101", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'e'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);
    TestNormalStr2CodeStr(
"11001", codeStr, &codeLen);
    assert(memcmp(dataCodeArr[
'f'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0);

    
for(i = 0; i < CODE_SIZE; ++i) {
        
if(dataCodeArr[i].pCode != NULL) {
            free(dataCodeArr[i].pCode);
            dataCodeArr[i].pCode 
= NULL;
        }

    }

}

/*
int main(void)
{
    TestCreateTestFile("Test.txt");
    Test_GetDataFreq();
    Test_BuildHuffmanTree();
    Test_GetFileHuffmanCode();
    Test_ReadWriteZipFileHead();
    return 0;
}
*/


/************************************************************************/
/*                      主程序函数                                      */
/************************************************************************/
int  main( void )
{
    
char *fileName = "Test.txt";
    
char *zipFileName = "ZipTest.txt";
    
char *unzipFileName = "UnzipTest.txt";

    ZipFile(fileName, zipFileName);
    UnzipFile(zipFileName, unzipFileName);
    
return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值