您的位置:首页 > 其它

[置顶] 哈夫曼编码应用之实现文件压缩

2016-07-30 00:35 363 查看
背景:为了锻炼自己的代码能力,以及数据结构算法掌握的能力,做此项目来锻炼自己提高自己的能力,本项目运用了C++中的知识,比如模板类,仿函数等等,还用到了数据结构中的算法知识,比如建堆调堆、哈夫曼编码,还用到了文件操作的知识。总是试一次很好的训练。

介绍一下哈夫曼编码:

哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。

下面列出实现文件压缩的C++代码:

建堆调堆头文件:Heap.h

#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__*/


建堆调堆实现文件:Heap.hpp

#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);
}
}
}


建立哈夫曼数头文件:HuffmanTree.h

#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



本项目特点:将压缩后的文件,以及配置文件新建立了一个文件夹,放在文件夹中,这样美观,易识别。

代码中还有很多不足,有些问题也未解决,欢迎各位批评指正!!!  我也会子啊后续努力中继续添加功能!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: