哈夫曼編碼應用之實現檔案壓縮
阿新 • • 發佈:2019-01-06
背景:為了鍛鍊自己的程式碼能力,以及資料結構演算法掌握的能力,做此專案來鍛鍊自己提高自己的能力,本專案運用了C++中的知識,比如模板類,仿函式等等,還用到了資料結構中的演算法知識,比如建堆調堆、哈夫曼編碼,還用到了檔案操作的知識。總是試一次很好的訓練。
介紹一下哈夫曼編碼:
哈夫曼編碼(Huffman Coding)是一種編碼方式,哈夫曼編碼是可變字長編碼(VLC)的一種。Huffman於1952年提出一種編碼方法,該方法完全依據字元出現概率來構造異字頭的平均長 度最短的碼字,有時稱之為最佳編碼,一般就叫作Huffman編碼。
下面列出實現檔案壓縮的C++程式碼:
建堆調堆標頭檔案:Heap.h
建堆調堆實現檔案:Heap.hpp#ifndef __HEAP_H__ #define __HEAP_H__ #include <iostream> #include <assert.h> #include <vector> #include "FileCompress.h" #include "HuffmanTree.h" template <typename T> struct Less { bool operator()(const T& left, const T& right)const { return left < right; } }; template<typename K> //模板的偏特化 struct Less<HuffmanNode<K>*> { bool operator()(const HuffmanNode<K>* left, const HuffmanNode<K>* right)const { return left->_weight < right->_weight; } }; //template <> //struct Less<CharInfo> //{ // bool operator()(const CharInfo& left, const CharInfo& right)const // { // return left < right; // } //}; template <typename T> struct Greater { bool operator()(const T& left, const T& right)const { return left > right; } }; template <typename T,template<class> class Compare = Greater> class Heap { friend std::ostream& operator<<<T,Compare>(std::ostream& out, const Heap<T,Compare>& heap); public: Heap(); Heap(const T* array, size_t size); Heap(const Heap<T,Compare>& heap); Heap<T,Compare>& operator=(const Heap<T, Compare>& heap); ~Heap(); void Push(const T& x); void Pop(); T Top()const; bool Empty()const; size_t Size()const; protected: void _AdjustDown(int parent); void _AdjustUp(int pos); protected: std::vector<T> _array; }; //堆排序 template <typename T, template<class> class Compare = Greater> void HeapSort(T* array, size_t size, const Compare<T>& com = Compare<T>()); //建初堆 template <typename T, template<class> class Compare = Greater> void CrtHeap(T* array, size_t size, const Compare<T>& com = Compare<T>()); //下調 template <typename T, template<class> class Compare = Greater> void AdjustDown(T* array, size_t size, int parent = 0, const Compare<T>& com = Compare<T>()); template <typename T, template<class> class Compare = Greater> std::ostream& operator<<(std::ostream& out, const Heap<T, Compare>& heap); template <typename T, template<class> class Compare = Greater> void GetTopK(T* array, const vector<T>& money, const size_t& k, const size_t& n, const Compare<T>& com = Compare<T>()); #endif /*__HEAP_H__*/
建立哈夫曼數標頭檔案:HuffmanTree.h#define _CRT_SECURE_NO_WARNINGS 1 #include "Heap.h" template <typename T,template<class> class Compare> Heap<T,Compare>::Heap() {} template <typename T,template<class> class Compare> Heap<T,Compare>::~Heap() {} template <typename T,template<class> class Compare> Heap<T,Compare>::Heap(const T* array, size_t size) { this->_array.resize(size); for (size_t i = 0; i < size; ++i) { this->_array[i] = array[i]; } for (int i = (size - 2) / 2; i >= 0; --i) { this->_AdjustDown(i); } } template <typename T,template<class> class Compare> Heap<T,Compare>::Heap(const Heap<T,Compare>& heap) { size_t size = heap.size(); this->_array.resize(size); for (size_t i = 0; i < size; ++i) { this->_array[i] = heap._array[i]; } } template <typename T,template<class> class Compare> Heap<T,Compare>& Heap<T,Compare>::operator=(const Heap<T,Compare>& heap) { if (this != &heap) { this->_array = heap._array; } return *this; } template <typename T,template<class> class Compare> void Heap<T,Compare>::Push(const T& x) { size_t size = this->_array.size(); this->_array.push_back(x); this->_AdjustUp(size); } //Compare template <typename T,template<class> class Compare> void Heap<T,Compare>::_AdjustUp(int pos) { assert(pos<this->_array.size()); Compare<T> com; int parent = (pos - 1) / 2; int child = pos; while (parent >= 0 && com(this->_array[child], this->_array[parent])) { swap(this->_array[child], this->_array[parent]); child = parent; parent = (child - 1) / 2; } } template <typename T,template<class> class Compare> void Heap<T,Compare>::Pop() { assert(!this->_array.empty()); size_t size = this->_array.size(); swap(this->_array[0], this->_array[size - 1]); this->_array.pop_back(); this->_AdjustDown(0); } //Compare template <typename T,template<class> class Compare> void Heap<T,Compare>::_AdjustDown(int parent) { size_t child = parent * 2 + 1; size_t size = this->_array.size(); Compare<T> com; while (child < size) { if (child + 1 < size && com(this->_array[child + 1], this->_array[child])) { ++child; } if (com(this->_array[child], this->_array[parent])) { swap(this->_array[parent], this->_array[child]); parent = child; child = parent * 2 + 1; } else { break; } } } template <typename T,template<class> class Compare> T Heap<T,Compare>::Top()const { assert(!this->_array.empty()); return this->_array[0]; } template <typename T,template<class> class Compare> bool Heap<T,Compare>::Empty()const { return this->_array.empty(); } template <typename T,template<class> class Compare> size_t Heap<T,Compare>::Size()const { return this->_array.size(); } template <typename T,template<class> class Compare> std::ostream& operator<<(std::ostream& out, const Heap<T,Compare>& heap) { size_t size = heap._array.size(); for (size_t i = 0; i < size; ++i) { out << heap._array[i] << " "; } out << endl; return out; } //堆排序 //template <typename T> //void HeapSort(T* array, size_t size) //{ // //建初堆 // Heap<T,Compare> heap(array, size); // for (int i = size - 1; i >= 0; --i) // { // array[i] = heap.GetTop(); // heap.Pop(); // } //} template <typename T,template<class> class Compare> void HeapSort(T* array, size_t size, const Compare<T>& com) { CrtHeap(array, size, com);//建初堆 for (int i = size - 1; i > 0; --i) { swap(array[0], array[i]); //交換頭和尾 AdjustDown(array, i, 0, com); //使得0...i-1也為堆 } } //建初堆 template <typename T, template<class> class Compare> void CrtHeap(T* array, size_t size, const Compare<T>& com) { int parent = (size - 2) / 2; for (int i = parent; i >= 0; --i) { AdjustDown(array, size, i, com); } } //下調 //Compare template <typename T,template<class> class Compare> void AdjustDown(T* array, size_t size, int parent, const Compare<T>& com) { int child = parent * 2 + 1; while (child < (int)size) { if (child + 1 < size && com(array[child + 1], array[child])) { ++child; } if (com(array[child], array[parent])) { swap(array[parent], array[child]); parent = child; child = parent * 2 + 1; } else { break; } } } template <typename T, template<class> class Compare> void GetTopK(T* array, const vector<T>& money, const size_t& k, const size_t& n, const Compare<T>& com) { assert(array); assert(k < n); for (size_t i = 0; i < k; ++i) { array[i] = money[i]; } //建堆 for (int i = (k - 2) / 2; i >= 0; --i) { AdjustDown(array, k, i, com); } for (int i = k; i < n; ++i) { if (com(array[0],money[i])) { array[0] = money[i]; AdjustDown(array, k, 0, com); } } }
#pragma once
#ifndef __HUFFMAN_TREE_H__
#define __HUFFMAN_TREE_H__
#include <iostream>
template <typename T>
struct HuffmanNode
{
T _weight;
HuffmanNode* _left;
HuffmanNode* _right;
HuffmanNode(T weight = 0) :_weight(weight), _left(NULL), _right(NULL)
{}
//建堆時要用
//bool operator<(const HuffmanNode* right)
//{
// return this->_weight < right->_weight;
//}
};
template <typename T>
class HuffmanTree
{
typedef HuffmanNode<T> Node;
public:
HuffmanTree();
HuffmanTree(const T* array, size_t size, int vailed = 0);
Node* GetHuffmanNode();
~HuffmanTree();
protected:
static Node* _CreateHuffmanTree(const T* array, size_t size, int vailed = 0);
static void _Clear(Node* root);
protected:
Node* _root;
};
#endif /*__HUFFMAN_TREE_H__*/
建立哈夫曼數實現檔案:HuffmanTree.hpp
#pragma once
#ifndef __HUFFMAN_TREE_HPP__
#define __HUFFMAN_TREE_HPP__
#include "Heap.hpp"
#include "HuffmanTree.h"
template <typename T>
HuffmanTree<T>::HuffmanTree() :_root(NULL)
{}
template <typename T>
HuffmanTree<T>::HuffmanTree(const T* array, size_t size, int vailed) : _root(NULL)
{
this->_root = _CreateHuffmanTree(array, size, vailed);
}
template <typename T>
HuffmanNode<T>* HuffmanTree<T>::_CreateHuffmanTree(const T* array, size_t size, int valid)
{
//選最小,減小堆
Heap<Node*, Less> heap;
Node* parent = NULL;
for (size_t i = 0; i < size; ++i)//往堆裡入結點
{
if (array[i] != valid)
{
heap.Push(new Node(array[i]));
}
}
while (heap.Size() > 1)
{
Node* minFirst = heap.Top();
heap.Pop();
Node* minSecond = heap.Top();
heap.Pop();
parent = new Node(minFirst->_weight + minSecond->_weight);
parent->_left = minFirst;
parent->_right = minSecond;
heap.Push(parent);
}
return parent;
}
template <typename T>
HuffmanTree<T>::~HuffmanTree()
{
this->_Clear(this->_root);
}
template <typename T>
void HuffmanTree<T>::_Clear(Node* root)
{
if (root)
{
_Clear(root->_left);
_Clear(root->_right);
delete root;
}
}
template <typename T>
HuffmanNode<T>* HuffmanTree<T>::GetHuffmanNode()
{
return this->_root;
}
#endif /*__HUFFMAN_TREE_HPP__*/
檔案壓縮標頭檔案:FileCompress.h
#pragma once
#ifndef __HUFFMAN_CODE_H__
#define __HUFFMAN_CODE_H__
#include <iostream>
#include <vector>
#include <string>
#include "HuffmanTree.h"
using namespace std;
typedef unsigned long long TypeLong;
struct CharInfo
{
unsigned char _ch; //字元
TypeLong _count;//出現次數
string _code;//Huffman編碼
CharInfo(TypeLong count = 0) :_ch(0), _count(count)
{}
bool operator!=(const CharInfo& info)const
{
return this->_count != info._count;
}
bool operator<(const CharInfo& info)const
{
return this->_count < info._count;
}
CharInfo operator+(const CharInfo& info)const
{
return CharInfo(this->_count + info._count);
}
};
class FileCompress
{
public:
FileCompress();
void CompressHuffCode(const char* filename);
void UnCompressHuffCode(const char* filename);
void PrintCode()const;
protected:
static void GenerateHuffmanCode(HuffmanNode<CharInfo>* root, FileCompress& file, string& code);
protected:
CharInfo _info[256];
};
#endif /*__HUFFMAN_CODE_H__*/
檔案壓縮實現檔案:FileCompreess.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <assert.h>
#include "FileCompress.h"
#include <io.h>
#include <direct.h>
#define __DEBUG_COUT__
FileCompress::FileCompress()
{
<span style="white-space:pre"> </span>size_t size = sizeof(this->_info) / sizeof(this->_info[0]);
<span style="white-space:pre"> </span>for (size_t i = 0; i < size; ++i)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>this->_info[i]._ch = i;
<span style="white-space:pre"> </span>this->_info[i]._count = 0;
<span style="white-space:pre"> </span>}
}
void FileCompress::CompressHuffCode(const char* filename)
{
<span style="white-space:pre"> </span>assert(filename);
<span style="white-space:pre"> </span>FILE* fOut = fopen(filename, "rb");
<span style="white-space:pre"> </span>assert(fOut);
<span style="white-space:pre"> </span>//統計字元出現的次數
<span style="white-space:pre"> </span>unsigned char ch = fgetc(fOut);
<span style="white-space:pre"> </span>while (!feof(fOut))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>++this->_info[(unsigned char)ch]._count;
<span style="white-space:pre"> </span>ch = fgetc(fOut);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>fseek(fOut, 0, SEEK_SET);
<span style="white-space:pre"> </span>//建立哈夫曼樹
<span style="white-space:pre"> </span>HuffmanTree<CharInfo> huffTree(this->_info, sizeof(this->_info) / sizeof(this->_info[0]), 0);
<span style="white-space:pre"> </span>//生成哈夫曼編碼
<span style="white-space:pre"> </span>string code;
<span style="white-space:pre"> </span>HuffmanNode<CharInfo>* root = huffTree.GetHuffmanNode();
<span style="white-space:pre"> </span>GenerateHuffmanCode(root, *this, code);
<span style="white-space:pre"> </span>//生成壓縮檔名及配置配置檔名
<span style="white-space:pre"> </span>string fileNewName = (string)filename;
<span style="white-space:pre"> </span>size_t last_ = fileNewName.find_last_of('.');
<span style="white-space:pre"> </span>size_t name_ = fileNewName.find_last_of('\\');//檔名
<span style="white-space:pre"> </span>if (last_ < fileNewName.size())
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fileNewName.erase(last_);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>char file[10], type[10];
<span style="white-space:pre"> </span>strcpy(file, filename + name_ + 1); //檔名
<span style="white-space:pre"> </span>strcpy(type, filename + last_ ); //檔案型別
<span style="white-space:pre"> </span>fileNewName += "_rar\\";
<span style="white-space:pre"> </span>char *fileName = (char *)fileNewName.c_str(), *tag, path[1000];
<span style="white-space:pre"> </span>strcpy(path, fileName);
<span style="white-space:pre"> </span>int a = 0;
<span style="white-space:pre"> </span>for (tag = fileName; *tag; tag++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>if (*tag == '\\')
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>a = strlen(fileName) - strlen(tag);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>path[a] = NULL;
<span style="white-space:pre"> </span>char filePath[1000];
<span style="white-space:pre"> </span>sprintf(filePath, "md %s", path);
<span style="white-space:pre"> </span>system(filePath);
<span style="white-space:pre"> </span>fileNewName += file;
<span style="white-space:pre"> </span>string fileInName = fileNewName;//壓縮檔名
<span style="white-space:pre"> </span>string fileConfig = fileInName;//配置檔名
<span style="white-space:pre"> </span>last_ = fileNewName.find_last_of('.');
<span style="white-space:pre"> </span>if (last_ < fileNewName.size())
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fileInName.erase(last_);
<span style="white-space:pre"> </span>fileConfig.erase(last_);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>fileInName += ".huff";
<span style="white-space:pre"> </span>fileConfig += ".config";
<span style="white-space:pre"> </span>string tmp;
<span style="white-space:pre"> </span>//生成壓縮配置檔案
<span style="white-space:pre"> </span>FILE* fConfig = fopen(fileConfig.c_str(), "wb");
<span style="white-space:pre"> </span>char *tyone = type;
<span style="white-space:pre"> </span>for (int i = 0; i < 10; i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fputc(*tyone,fConfig);
<span style="white-space:pre"> </span>tyone++;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>char buff[20] = { 0 };
<span style="white-space:pre"> </span>for (size_t i = 0; i < sizeof(this->_info) / sizeof(this->_info[0]); ++i)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>tmp.clear();
<span style="white-space:pre"> </span>if (this->_info[i]._count != 0)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>tmp += this->_info[i]._ch;
<span style="white-space:pre"> </span>tmp += ':';
<span style="white-space:pre"> </span>tmp += (string)_itoa((this->_info[i]._count), buff, 10);
<span style="white-space:pre"> </span>tmp += '\n';
<span style="white-space:pre"> </span>fputs(tmp.c_str(), fConfig);<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>//對檔案進行壓縮
<span style="white-space:pre"> </span>FILE* fIn = fopen(fileInName.c_str(), "wb");
<span style="white-space:pre"> </span>assert(fIn);
<span style="white-space:pre"> </span>int pos = 0;
<span style="white-space:pre"> </span>unsigned char putch = 0;
<span style="white-space:pre"> </span>ch = fgetc(fOut);
<span style="white-space:pre"> </span>while (!feof(fOut))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>tmp = this->_info[(unsigned char)ch]._code;
<span style="white-space:pre"> </span>for (size_t i = 0; i < tmp.size(); ++i)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>putch <<= 1;
<span style="white-space:pre"> </span>putch |= (tmp[i] - '0');
<span style="white-space:pre"> </span>if (++pos == 8)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fputc(putch, fIn);
<span style="white-space:pre"> </span>pos = 0;
<span style="white-space:pre"> </span>putch = 0;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>ch = fgetc(fOut);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if (pos > 0)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>putch <<= (8 - pos);
<span style="white-space:pre"> </span>fputc(putch, fIn);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>fclose(fOut);
<span style="white-space:pre"> </span>fclose(fIn);
<span style="white-space:pre"> </span>fclose(fConfig);
}
void FileCompress::GenerateHuffmanCode(HuffmanNode<CharInfo>* root, FileCompress& file, string& code)
{
<span style="white-space:pre"> </span>if (root == NULL)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>return;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if (root->_left == NULL && root->_right == NULL)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>file._info[root->_weight._ch]._code = code;
<span style="white-space:pre"> </span>return;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>code.push_back('0');
<span style="white-space:pre"> </span>GenerateHuffmanCode(root->_left, file, code);
<span style="white-space:pre"> </span>code.pop_back();
<span style="white-space:pre"> </span>code.push_back('1');
<span style="white-space:pre"> </span>GenerateHuffmanCode(root->_right, file, code);
<span style="white-space:pre"> </span>code.pop_back();
}
void FileCompress::UnCompressHuffCode(const char* filename)
{
<span style="white-space:pre"> </span>assert(filename);
<span style="white-space:pre"> </span>FILE* fOut = fopen(filename, "rb");
<span style="white-space:pre"> </span>assert(fOut);
<span style="white-space:pre"> </span>//讀取檔案,
<span style="white-space:pre"> </span>string fileConfig = (string)filename;
<span style="white-space:pre"> </span>string fileNewName = (string)filename;
<span style="white-space:pre"> </span>string fileInName = fileConfig;
<span style="white-space:pre"> </span>size_t last_ = fileInName.find_last_of('.');
<span style="white-space:pre"> </span>size_t name_ = fileNewName.find_last_of('\\');
<span style="white-space:pre"> </span>if (name_ < fileNewName.size())
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fileConfig.erase(last_);
<span style="white-space:pre"> </span>fileNewName.erase(name_);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>char file[10];
<span style="white-space:pre"> </span>strcpy(file, fileConfig.c_str() + name_ + 1);//檔名
<span style="white-space:pre"> </span>name_ = fileNewName.find_last_of('\\');
<span style="white-space:pre"> </span>if (name_ < fileInName.size())
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fileInName.erase(name_+1);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>fileInName += file; //彌補檔名
<span style="white-space:pre"> </span>fileConfig += ".config";
<span style="white-space:pre"> </span>FILE* fConfig = fopen(fileConfig.c_str(), "rb");
<span style="white-space:pre"> </span>assert(fConfig);
<span style="white-space:pre"> </span>//修改_count,注意\n,有可能代表字元,有可能是行結束標誌
<span style="white-space:pre"> </span>char buff[20] = { 0 }, type[10] = { 0 };
<span style="white-space:pre"> </span>char *tyone = type;
<span style="white-space:pre"> </span>for (int i = 0; i < 10; i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>*tyone = fgetc(fConfig);
<span style="white-space:pre"> </span>tyone++;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>unsigned char ch = fgetc(fConfig);
<span style="white-space:pre"> </span>while (!feof(fConfig))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fgetc(fConfig);//讀取冒號
<span style="white-space:pre"> </span>fgets(buff, 20, fConfig);
<span style="white-space:pre"> </span>this->_info[ch]._count = (TypeLong)atoi((buff));
<span style="white-space:pre"> </span>ch = fgetc(fConfig);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>fileInName += "_unrar";
<span style="white-space:pre"> </span>fileInName += type;
<span style="white-space:pre"> </span>FILE* fIn = fopen(fileInName.c_str(), "wb");
<span style="white-space:pre"> </span>assert(fIn);
<span style="white-space:pre"> </span>//重建哈夫曼樹
<span style="white-space:pre"> </span>HuffmanTree<CharInfo> tree(this->_info, sizeof(this->_info) / sizeof(this->_info[0]), 0);
<span style="white-space:pre"> </span>HuffmanNode<CharInfo>* root = tree.GetHuffmanNode();
<span style="white-space:pre"> </span>HuffmanNode<CharInfo>* cur = root;
<span style="white-space:pre"> </span>TypeLong countSum = root->_weight._count; //記錄字元的總個數控制結束
<span style="white-space:pre"> </span>ch = fgetc(fOut);
<span style="white-space:pre"> </span>int pos = 7;
<span style="white-space:pre"> </span>while (countSum > 0)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>while (pos >= 0)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>if ((ch & (1 << pos)) == 0) //向左走
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>cur = cur->_left;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>else
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>cur = cur->_right;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if (cur->_left == NULL && cur->_right == NULL)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fputc(cur->_weight._ch, fIn);
#ifndef __DEBUG_COUT__
<span style="white-space:pre"> </span>cout << cur->_weight._ch;
#endif /*__DEBUG_COUT__*/
<span style="white-space:pre"> </span>if (--countSum == 0)//將沒有寫的字元的次數減1
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>cur = root;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>--pos;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>pos = 7;
<span style="white-space:pre"> </span>ch = fgetc(fOut);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>fclose(fIn);
<span style="white-space:pre"> </span>fclose(fOut);
<span style="white-space:pre"> </span>fclose(fConfig);
}
void FileCompress::PrintCode()const
{
<span style="white-space:pre"> </span>for (int i = 0; i < 256; ++i)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>if (this->_info[i]._count != 0)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>cout << this->_info[i]._ch << ":>" << this->_info[i]._code << endl;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
}
測試程式碼:壓縮測試函式,放在主函式裡
void test()
{
string filename = "C:\\Users\\小明\\Desktop\\input.txt";
cout << "壓縮時間";
MyTimer timer;
timer.Start();
////////////////////////////////
FileCompress fc;
fc.CompressHuffCode(filename.c_str());
/////////////////////////////////
timer.Stop();
timer.showTime();
}
測試程式碼:解壓縮測試函式,放在主函式裡void untest()
{
string filename = "C:\\Users\\小明\\Desktop\\input_rar\\input.huff";
cout << "解壓時間";
MyTimer timer;
timer.Start();
////////////////////////////////
FileCompress unfc;
unfc.UnCompressHuffCode(filename.c_str());
/////////////////////////////////
timer.Stop();
timer.showTime();
}
主函式:test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include "HuffmanTree.hpp"
#include "FileCompress.h"
#include "FileCompress.cpp"
#include "TimeCheck.h"
void test()
{
string filename = "C:\\Users\\小明\\Desktop\\input.txt"; //需要壓縮的檔案
cout << "壓縮時間";
MyTimer timer;
timer.Start();
////////////////////////////////
FileCompress fc;
fc.CompressHuffCode(filename.c_str());
/////////////////////////////////
timer.Stop();
timer.showTime();
}
void untest()
{
string filename = "C:\\Users\\小明\\Desktop\\input_rar\\input.huff"; //需要解壓縮的檔名
cout << "解壓時間";
MyTimer timer;
timer.Start();
////////////////////////////////
FileCompress unfc;
unfc.UnCompressHuffCode(filename.c_str());
/////////////////////////////////
timer.Stop();
timer.showTime();
}
int main()
{
test();
untest();
system("pause");
return 0;
}
現在測試的是我桌面上的一個檔案:檔名為:input.txt
壓縮過程
壓縮和解壓縮之後桌面顯示:
解壓縮檔案:input_Com.txt
本專案特點:將壓縮後的檔案,以及配置檔案新建立了一個資料夾,放在資料夾中,這樣美觀,易識別。
程式碼中還有很多不足,有些問題也未解決,歡迎各位批評指正!!! 我也會子啊後續努力中繼續新增功能!