压缩与解压缩的实现

参考网址:
开源代码:http://www.zlib.net
zlib使用手册:http://www.zlib.net/manual.html
zlib wince版:http://www.tenik.co.jp/~adachi/wince/
在这里,你可以查看基于各种操作系统平台的压缩与解缩代码实现。

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
以下是经过测试的 WinCE 及 WinXP 下的代码

<<<<<<<<
第一步: 首先到www.zlib.net下载个ZLIB,
             WinXP: 解压缩后打开zlib-1.2.3/projects/visualc6/zlib.dsw,选择Win32 LIB Release 按F7编绎生成zlib.lib, zlib.dll.
            WinCE: 下载一个for Windows CE 版的包,里面针对各种平台(ARM4, ARM4I, MIPS, X86)有对应的zlibce.dll zlibce.lib.

<<<<<<<<
第二步: 建立EVC 或者 VC6 的对话框工程.
             在工程中添加以下文件:zlib.h, zconf.h, zlib.lib, zlib.dll (或者 zlibce.dll);
            这3个文件就在刚才从www.zlib.net下载的软件包中.

<<<<<<<<
第三步: 包含头文件
#include "zlib.h"
#include "StorageDeal.h"
      其中CStorageDeal是我写的文件处理类,功能类似于CFile类。它的类定义如下:
class CStorageDeal : public CStatic
{
     // Construction
     public:
         CStorageDeal();
         virtual ~CStorageDeal();

     // Attributes
     public:
       CFile myFile;
        DWORD myFileLength;
       BOOL FileOpenStaus;

     public:
        BOOL OpenFile(CString pFileName); 
        BOOL CloseFile();

        DWORD ReadBlockData(BYTE *pData, DWORD blockIndex, DWORD idIndex);
      DWORD WriteBlockData(BYTE *pData, DWORD blockIndex, DWORD idIndex);

        DWORD GetFileLength();
        DWORD SetFileLength(DWORD length); 

        DWORD ReadData(BYTE *pData, DWORD position, DWORD length);
      DWORD WriteData(BYTE *pData, DWORD position, DWORD length);

        static BOOL DeleteFile(CString pFileName);
       static BOOL RenameFile(CString pOldName, CString pNewName);
};

<<<<<<<<
第四步: 添加压缩与解压缩代码

压缩代码:
BOOL CMyZip_evcDlg::zip(CString srcFileName, CString dstFileName)
{

#ifdef NO_GZCOMPRESS

    MessageBox(_T("NO_GZCOMPRESS -- gz* functions cannot compress"));

       return FALSE;

#endif

       // 打开待压缩的文件

       CStorageDeal unzipFile;

       unzipFile.OpenFile(srcFileName);

       int fileLen = unzipFile.GetFileLength();

       // 创建压缩文件

    gzFile zipFile;

       CString zipFileName = srcFileName +_T(".gz");

       int zipFileNameLen = zipFileName.GetLength();

#ifdef ARM   // WinCE下代码

       char nameBuff[100]={0};

    WideCharToMultiByte(CP_ACP,0,zipFileName,zipFileNameLen,nameBuff,zipFileNameLen,NULL,NULL);

       zipFile = gzopen(nameBuff, "wb");

#else // WinXP下大妈

       zipFile = gzopen(zipFileName, "wb");

#endif

      

    z_off_t pos;

      

       // 临时变量定义

       BYTE buff[10000]={0};

       int buffLen;

       int BlockSize = sizeof(buff);

       int BlockLeft = fileLen%BlockSize;

       int BlockNum = fileLen/BlockSize;

       if(BlockLeft != 0)

       {

              BlockNum++;

       }

      

       // 开始压缩

       for(int BlockIndex=0;BlockIndex<BlockNum;BlockIndex++)

       {

              if(BlockLeft != 0)

              {

                     if(BlockIndex < BlockNum - 1)

                            buffLen = BlockSize;

                     else

                            buffLen = BlockLeft;

              }

              else

              {

                     buffLen = BlockSize;

              }

             

              unzipFile.ReadData(buff,BlockIndex*BlockSize,buffLen);

             

             

              if (zipFile == NULL)

              {

                     MessageBox(_T("gzopen error/n"));

                     return FALSE;

              }

#ifdef ARM

              gzwrite(zipFile,(voidp)buff,buffLen);

#else

              gzwrite(zipFile,(voidpc)buff,buffLen);

#endif

       }

       gzclose(zipFile);

       unzipFile.CloseFile();

      

       // dest file name is not processed.

       // CFile::Rename(zipFileName,dstFileName);

}


解压缩代码:

BOOL CMyZip_evcDlg::unzip(CString srcFileName, CString dstFileName)

{

       // 打开待解压的文件

    gzFile zipFile;

       CString zipFileName = srcFileName;

       int zipFileNameLen = zipFileName.GetLength();

#ifdef ARM

       char nameBuff[100]={0};

    WideCharToMultiByte(CP_ACP,0,zipFileName,zipFileNameLen,nameBuff,zipFileNameLen,NULL,NULL);

       zipFile = gzopen(nameBuff, "rb");

#else

       zipFile = gzopen(zipFileName, "rb");

#endif

      

    if (zipFile == NULL) {

        MessageBox(_T("gzopen error"));

              return FALSE;

    }

       // 创建文件

       CStorageDeal unzipFile;

       dstFileName = srcFileName;

       dstFileName.TrimRight(_T(".gz"));

      

       unzipFile.OpenFile(dstFileName);

       unzipFile.SetFileLength(0);

      

       // 临时变量

       BYTE buff[1000]={0};

       int buffLen = sizeof(buff);

      

       // 开始解压

       int len;

       int pos = 0;

       while(1)

       {

              len = gzread(zipFile, (voidp)buff,buffLen);

              if(len==0) break;

             

              unzipFile.WriteData(buff,pos,len);

              pos += len;

       }

       gzclose(zipFile);

       unzipFile.CloseFile();

}

 

<<<<<<<<
第五步: 调用压缩与解压缩代码

void CMyZIP_vc6Dlg::OnButton1()

{

       zip(_T("d://aa.doc"),_T("aa.doc.gz"));  
}

void CMyZIP_vc6Dlg::OnButton2()

{

       unzip(_T("d://aa.doc.gz"),_T("aa.doc"));

}

 

<<<<<<<<

哈夫曼编码是一种基于字符频率的压缩算法,可以在不丢失数据的情况下有效地减小文件大小。哈夫曼编码的压缩过程需要先建立哈夫曼树,再根据哈夫曼树生成每个字符的编码表,最后将原文件中的字符替换为对应的编码即可。解压过程则是将编码转换为原字符,最终还原原始文件。 以下是一个简单的哈夫曼树编码文件压缩解压缩实现示例,使用 C++ 语言编写。 ### 哈夫曼树的构建 ```cpp #include <iostream> #include <queue> #include <vector> #include <unordered_map> using namespace std; // 哈夫曼树节点 struct Node { char ch; int freq; Node *left, *right; Node(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {} }; // 比较器,用于优先队列中的排序 struct cmp { bool operator()(Node* a, Node* b) { return a->freq > b->freq; } }; // 构建哈夫曼树 Node* buildHuffmanTree(string str) { // 统计字符频率 unordered_map<char, int> freqMap; for (char c : str) { freqMap[c]++; } // 将所有字符及其频率转化为哈夫曼树节点并加入优先队列 priority_queue<Node*, vector<Node*>, cmp> pq; for (auto it = freqMap.begin(); it != freqMap.end(); it++) { pq.push(new Node(it->first, it->second)); } // 构建哈夫曼树 while (pq.size() > 1) { Node* left = pq.top(); pq.pop(); Node* right = pq.top(); pq.pop(); Node* parent = new Node('$', left->freq + right->freq); parent->left = left; parent->right = right; pq.push(parent); } // 返回根节点 return pq.top(); } ``` ### 哈夫曼编码的生成 ```cpp // 生成哈夫曼编码表 void generateEncodingTable(Node* root, unordered_map<char, string>& encodingTable, string code) { if (!root) return; if (!root->left && !root->right) { encodingTable[root->ch] = code; return; } generateEncodingTable(root->left, encodingTable, code + "0"); generateEncodingTable(root->right, encodingTable, code + "1"); } ``` ### 文件压缩 ```cpp #include <fstream> #include <bitset> // 压缩文件 void compressFile(string inputFile, string outputFile) { // 读取原文件 ifstream ifs(inputFile, ios::binary); string str((istreambuf_iterator<char>(ifs)), (istreambuf_iterator<char>())); ifs.close(); // 构建哈夫曼树并生成编码表 Node* root = buildHuffmanTree(str); unordered_map<char, string> encodingTable; generateEncodingTable(root, encodingTable, ""); // 将编码表写入压缩文件头部 ofstream ofs(outputFile, ios::binary); for (auto it = encodingTable.begin(); it != encodingTable.end(); it++) { ofs << it->first << it->second << endl; } // 将压缩后的内容写入压缩文件 string compressedStr; for (char c : str) { compressedStr += encodingTable[c]; } while (compressedStr.length() % 8 != 0) compressedStr += "0"; // 补齐到8的倍数 for (int i = 0; i < compressedStr.length(); i += 8) { bitset<8> bits(compressedStr.substr(i, 8)); ofs << char(bits.to_ulong()); } ofs.close(); } ``` ### 文件解压 ```cpp #include <sstream> // 解压文件 void decompressFile(string inputFile, string outputFile) { // 读取压缩文件 ifstream ifs(inputFile, ios::binary); stringstream ss; ss << ifs.rdbuf(); string compressedStr = ss.str(); ifs.close(); // 从压缩文件头部读取编码表 unordered_map<string, char> decodingTable; int i = 0; while (i < compressedStr.length() && compressedStr[i] != '\n') { char c = compressedStr[i++]; string code; while (i < compressedStr.length() && compressedStr[i] != '\n') { code += compressedStr[i++]; } decodingTable[code] = c; i++; // 跳过换行符 } // 解压缩内容 string decompressedStr; string code; for (; i < compressedStr.length(); i++) { bitset<8> bits(compressedStr[i]); code += bits.to_string(); if (decodingTable.find(code) != decodingTable.end()) { decompressedStr += decodingTable[code]; code.clear(); } } // 写入解压后的内容 ofstream ofs(outputFile, ios::binary); ofs << decompressedStr; ofs.close(); } ``` 以上就是一个简单的哈夫曼树编码文件压缩解压缩实现方法。需要注意的是,在实际应用中,还需要考虑一些细节问题,例如文件读写、编码表的存储方式和压缩文件头部的格式等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值