中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

文件壓縮與解壓-創新互聯

文件的壓縮與解壓

專注于為中小企業提供成都網站設計、成都網站建設服務,電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業高明免費做網站提供優質的服務。我們立足成都,凝聚了一批互聯網行業人才,有力地推動了1000+企業的穩健成長,幫助中小企業通過網站建設實現規模擴充和轉變。

開發環境:vs2013

開發技術:vector、堆、哈夫曼樹、文件部分函數的操作

項目描述:文件壓縮是把一個占內存比較大的文件壓縮成為一個占內存比較小的文件,節省了磁盤的空                間,傳輸時也比較方便。解壓是把壓縮的文件還原成原來的文件,讀寫比較方便。

                     √可以壓縮與解壓小文件,也可以壓縮與解壓大文件。

                  √ 在Debug下,壓縮和解壓6M左右文件,需要25s左右,在Release下,需要2s左右。

                     √ 有配置文件,壓縮開發技術:vector、堆、哈夫曼樹、文件部分函數的操作

遇到的問題:√ 在壓縮過程中不夠8位會補零,但在解壓過程中會把零讀出來,這樣就不對了。為了解決                  這個問題。我在解壓過程中定義了一個總長度,它寫入一個字符,總長度就減1,當長度                  減為0,就不進去了。

                  √ 有時解壓大文件時,字數不想等。于是我就把’w’換成了’wb’,把’r'換了’rb’因                     為用文本模式打開時,遇到’\n’,會多加’\r’,但用二進制模式打開就不會有這樣的                     問題。

                  √ 有時讀大文件時,會讀不全。因此我就把EOF換成了feof。因為EOF是以-1為結束標志                       的,但文件中出現-1它就不會讀下去了。如果換成feof的話,它是以“文件結束”為標                       志。這樣就不會出現讀不完的情況。

compress.h中

#ifndef __Compress_H_
#define __Compress_H_

#include <string>
typedef long long LongType;

struct CharInfo
{
	unsigned char _ch;//字符
	LongType _count;//出現次數
	string _code;//哈夫曼編碼
	CharInfo(unsigned char ch = '0')
		:_ch(ch)
		, _count(0)
		, _code("")
	{}
	CharInfo(LongType count)
		:_count(count)
		, _ch(0)
		, _code("")
	{}
	//重載運算符“>”
	bool operator >(const CharInfo& com)const
	{
		return _count > com._count;
	}
	//重載運算符“!=”
	bool operator !=(CharInfo com)const 
	{
		return _count != com._count;
	}
	//重載運算符“+”
	CharInfo operator+(const CharInfo& com)const
	{
		return CharInfo(_count + com._count);
	}
};

class FileCompress
{
public:
	//壓縮
	FileCompress()
	{
		for (size_t i = 0; i < 256; i++)
		{
			_info[i]._ch = i;
		}
	}
	void Compress(const char* file)
	{
		//讀取文件
		FILE *fout = fopen(file, "rb");
		unsigned char ch = 0;
		assert(fout);
		//統計每個字符出現的次數
		ch = fgetc(fout);
		while (!feof(fout))
		{
			_info[(unsigned char)ch]._count++;
			ch = fgetc(fout);
		}
		//用次數建立哈夫曼樹
		const CharInfo invalid((unsigned char)0);
		HaffmanTree<CharInfo> tree(_info, 256,invalid);
		//生成哈夫曼編碼
		string tmp;
		_CreateHaffmanCode(tree.GetRoot(), tmp);
		//壓縮
		fseek(fout, 0, SEEK_SET);//從文件的首字符開始壓縮
		//壓縮后的文件名
		string comfile = file;
		comfile += ".haffman";
		FILE *fin = fopen(comfile.c_str(), "wb");
		assert(fin);
		unsigned char value = 0;
		size_t index = 0;//標記當前位
		ch = fgetc(fout);
		while (!feof(fout))
		{
			string code = _info[ch]._code;
			for (size_t i = 0; i < code.size(); i++)
			{
				if (code[i] == '1')
				{
					value <<= 1;
					value |= 1;
				}
				else
				{
					value <<= 1;
				}
				//滿8個字節,將其寫入到壓縮文件中
				if (++index == 8)
				{
						fputc(value, fin);
					    value = 0;
					     index = 0;
				}
			}
			ch = fgetc(fout);
		}
		//如果寫入完,value 沒有寫滿8位,把剩余的壓入壓縮文件中
		if (index != 0)
		{
			value <<= (8 - index);
			fputc(value, fin);
		}
		//配置文件
		string configfile = file;
		configfile += ".config";
		FILE* finfo = fopen(configfile.c_str(), "wb");
		assert(finfo);
		//將字符的總個數寫進配置文件
		char infostr[32];
		//將出現的字符以及次數寫進配置文件
		string str;
		for (size_t j = 0; j < 256; j++)
		{
				if (_info[j]._count > 0)
				{
					str.push_back((unsigned char)j);
					str.push_back(',');
					_itoa(_info[j]._count, infostr, 10);
					str += infostr;
					fputs(str.c_str(), finfo);
					fputc('\n', finfo);
					str.clear();
				}
		}
		fclose(fout);
		fclose(fin);
		fclose(finfo);
	}
	//解壓
	void UnCompress(const char *file)
	{
		unsigned char ch = 0;
		string fconfig = file;
		fconfig += ".config";
		//讀壓縮文件
		FILE* fout = fopen(fconfig.c_str(), "rb");
		assert(fout);
		string tmp;
		//字符出現的次數
		while (ReadLine(fout, tmp))
		{
			if (!tmp.empty())
			{
				//那到字符
				ch = tmp[0];
				//獲取字符的次數
				_info[(unsigned char)ch]._count = atoi(tmp.substr(2).c_str());
				tmp.clear();
			}
			else
			{
				tmp = '\n';
			}
		}
		//重建哈夫曼樹
		CharInfo invalid((unsigned char)0);
		HaffmanTree<CharInfo> h(_info, 256, invalid);
		HaffmanTreeNode<CharInfo>*root = h.GetRoot();
		//解壓
		string output = file;
		output += ".uncom";
		FILE* fin = fopen(output.c_str(), "wb");
		assert(fin);
		//根據壓縮文件,還原文件
		string Haffmanfile = file;
		Haffmanfile += ".haffman";
		FILE* fcom = fopen(Haffmanfile.c_str(), "rb");
		assert(fcom);
		HaffmanTreeNode<CharInfo>*cur = root;
		ch = fgetc(fcom);
		int pos = 8;
		LongType len = root->_weight._count;
		while (len > 0)
		{
			while (cur->_left &&cur->_right)
			{
				if (pos == 0)
				{
					ch = fgetc(fcom);
					pos = 8;
				}
				--pos;
				//與1,走右樹
				if (ch&(1 << pos))
				{
					cur = cur->_right;
				}
				//與0,走左樹
				else
				{
					cur = cur->_left;
				}
			}
			if (cur)
			{
				fputc(cur->_weight._ch, fin);//寫進解壓文件
				cur = root;
			}
			--len;
		}
		fclose(fout);
		fclose(fin);
		fclose(fcom);
	}
protected:
	//創建哈夫曼編碼
	void _CreateHaffmanCode(HaffmanTreeNode<CharInfo>*root, string tmp)
	{
		//判空
		if (root == NULL)
		{
			return;
		}
		if (root->_left == NULL&&root->_right == NULL)
		{
			//找到下標,把編碼寫到_code中
			int index = (root->_weight)._ch;
			_info[index]._code = tmp;
		}
		else
		{
			//左樹寫0
			if (root->_left)
			{
				tmp.push_back('0');
				_CreateHaffmanCode(root->_left, tmp);
				tmp.pop_back();
			}
			//右樹寫1
			if (root->_right)
			{
				tmp.push_back('1');
				_CreateHaffmanCode(root->_right, tmp);
				tmp.pop_back();
			}
		}
	}
	//讀一行
	bool ReadLine(FILE* file, string& tmp)
	{
		assert(file);
		char ch = fgetc(file);
		if (feof(file))
		{
			return false;
		}
		while (ch != '\n')
		{
			tmp += ch;
			ch = fgetc(file);
		}
		return true;
	}
protected:
	CharInfo _info[256];
};
#endif //__Compress_H_

HaffmanTree.h中

#ifndef __HaffmanTree_H_
#define __HaffmanTree_H_
#include "Heap.h"
template<class T>
struct  HaffmanTreeNode
{
	typedef HaffmanTreeNode<T> Node;

	T _weight;
	Node* _left;
	Node* _right;

	HaffmanTreeNode(const T& weight)
		:_weight(weight)
		, _left(NULL)
		, _right(NULL)
	{}
};

template<class T>
class HaffmanTree
{
	typedef HaffmanTreeNode<T> Node;
public:
	HaffmanTree()
		:_root(NULL)
	{}
	HaffmanTree(const T* arr, size_t size)
	{
		_root = _Create(arr, size);
	}
	//構造函數
	HaffmanTree(const T* arr, size_t size, const T& invalid)
	{ 
		_root = _Create(arr, size, invalid);
	}

	~HaffmanTree()
	{
		if (_root)
		{
			_Destroy(_root);
		}
	}

	Node* GetRoot()
	{
		return _root;
	}

protected:
	//創建哈夫曼樹
	Node* _Create(const T* arr, size_t size, const T& invalid)
	{ 
		struct compare
		{
			bool operator ()(const Node *left, const Node *right)
			{
				return left->_weight > right->_weight;
			}
		};

		Heap<Node*,compare>  _heap;
		//把值放到vector中
		for (size_t i = 0; i < size; ++i)
		{
			if (arr[i] != invalid)
			{
				Node *tmp = new Node(arr[i]);
				_heap.Push(tmp);
			}
		}
		//構造哈夫曼樹
		while (_heap.Size() > 1)
		{
			Node *left = _heap.Top();
			_heap.Pop();
			Node*right = _heap.Top();
			_heap.Pop();

			Node *parent = new Node(left->_weight + right->_weight);
			parent->_left = left;
			parent->_right = right;

			_heap.Push(parent);
		}

		return _heap.Top();
	}
	//釋放節點
	void _Destroy(Node* root)
	{ 
		if (root->_left == NULL && root->_right == NULL)
		{
			delete root;
			root = NULL;
		}
		else
		{
			_Destroy(root->_left);
			_Destroy(root->_right);
		}
	}

private:
	Node *_root;
};
#endif //__HaffmanTree_H_

Heap.h中

#ifndef __Heap_H_
#define __Heap_H_

#include<vector>
#include<assert.h>
template<class T>
//比較器
class Less
{
public:
	bool operator() (const T& left, const T& right)
	{
		return left > right;
	}
};

template<class T>
class Greater
{
public:
	bool operator() (const T& left, const T& right)
	{
		return left < right;
	}
};

template<class T, class Compare = Less<T> >
class Heap
{
public:
	//構造函數
	Heap()
		:_arr(NULL)
	{}
	Heap(const T* arr, int size)
	{
		assert(arr);
		_arr.reserve(size);

		for (int i = 0; i < size; i++)
		{
			_arr.push_back(arr[i]);
		}

		int begin = _arr.size() / 2 - 1;
		while (begin >= 0)
		{
			_AdjustDown(begin);
			begin--;         
		}
	}
	//拷貝構造
	Heap(vector<T>& s)
	{
		_arr = s;
		int begin = _arr.size() / 2 - 1;
		while (begin >= 0)
		{
			_AdjustDown(begin);
			begin--;            
		}
	}
	void Push(const T& x)
	{
		_arr.push_back(x);
		int begin = _arr.size();
		_AdjustUp(begin);
	}

	void Pop() 
	{
		_arr[0] = _arr[_arr.size() - 1];
		_arr.pop_back();
		_AdjustDown(0);
	}

	void Clear()
	{
		_arr.clear();
	}

	bool Empty()
	{
		return _arr.empty();
	}

  T& Top() 
	{
		if (!Empty())
		{
			return _arr[0];
		}
		exit(1);
	}

	size_t Size()
	{
		return _arr.size();
	}

protected:
	//下調
	void _AdjustDown(int parent)
	{ // 從根節點向下調整
		int size = _arr.size();
		int left = parent * 2 + 1;
		int right = left + 1;
		int key = left;
		while (left < size)
		{//Compare()仿函數
			//if (right < size && array[left] > array[right])
			if (right < size && Compare()(_arr[left], _arr[right]))  //右邊小
			{
				key = right;
			}
			else
			{
				key = left;
			}
			//if ((array[key] > array[parent]))
			if (Compare()(_arr[key], _arr[parent]))
			{
				break;
			}
			//else if (array[parent] > array[key])
			else if (Compare()(_arr[parent], _arr[key])) //左邊小
			{
				swap(_arr[key], _arr[parent]);
			}

			parent = key;
			left = parent * 2 + 1;
			right = left + 1;
		}
	}
	//上調
	void _AdjustUp(int child)
	{  //從葉子節點或子節點向上調整
		int size = _arr.size();
		if (size == 0 || size == 1)
		{
			return;
		}

		int parent = (child - 2) / 2;
		int left = parent * 2 + 1;
		int right = left + 1;
		int key = 0;
		while (parent >= 0)
		{
			//if (right < size && array[left] > array[right])
			if (right < size && Compare()(_arr[left], _arr[right]))
			{
				key = right;
			}
			else
			{
				key = left;
			}
			//if (array[parent] > array[key])
			if (Compare()(_arr[parent], _arr[key]))
			{
				swap(_arr[parent], _arr[key]);
			}
			else
			{
				break;
			}

			if (parent == 0)
			{
				break;
			}

			parent = (parent - 1) / 2;
			left = parent * 2 + 1;
			right = left + 1;
		}
	}

private:
	vector<T> _arr; 
};

#endif //__Heap_H_

test.cpp中

#define _CRT_SECURE_NO_WARNINGS 1
#include<time.h>
#include <iostream>
using namespace std;

#include "HaffmanTree.h"
#include "Compress.h"
void Test()
{
	double t1;
	double t2;
	FileCompress f;
	//f.Compress("input.txt");
	f.Compress("mnt.txt");
	t1 = clock();
	printf("壓縮文件需要的時間: %f s \n", t1 / CLOCKS_PER_SEC);
	//f.UnCompress("input.txt");
	f.UnCompress("mnt.txt");
	t2 = clock();
	printf("解壓縮文件需要的時間: %f s \n", t2 / CLOCKS_PER_SEC);
}
int main()
{
	Test();
	system("pause");
	return 0;
}

另外有需要云服務器可以了解下創新互聯scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業上云的綜合解決方案,具有“安全穩定、簡單易用、服務可用性高、性價比高”等特點與優勢,專為企業上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。

網站題目:文件壓縮與解壓-創新互聯
文章源于:http://m.2m8n56k.cn/article28/dipejp.html

成都網站建設公司_創新互聯,為您提供ChatGPTGoogle企業建站全網營銷推廣軟件開發手機網站建設

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

微信小程序開發
主站蜘蛛池模板: 国产高清精品在线 | 亚洲精品天堂一区 | 亚洲国产精品网站久久 | 国产成人在线播放视频 | 九九视频在线看精品 | 色在线免费视频 | 国产伦精品一区二区三区无广告 | 日本三级香港三级人妇gg在线 | 久草一级片 | 国亚洲欧美日韩精品 | 精品一区二区三区视频 | 日本免费久久 | 久草在线在线观看 | 成人久久精品一区二区三区 | 日韩美女一区 | 女人张开双腿让男人桶爽免 | 欧美性69| 国产一级爱做片免费观看 | 国产美女毛片 | 99免费精品 | 欧美大狠狠大臿蕉香蕉大视频 | 亚洲精品专区一区二区欧美 | 久久久久9999 | 综合自拍亚洲综合图区美腿丝袜 | 成人精品视频一区二区在线 | 国产成人综合欧美精品久久 | 国产三级a | 精产网红自拍在线 | 日本亚欧乱色视频在线网站 | 男女乱配视频免费观看 | 亚洲高清二区 | 国产一级一片免费播放刺激 | 私人玩物福利视频 | 亚洲男人的天堂网 | 亚洲一区二区三 | 久久精品2 | 国产美女精品视频 | 欧美成人精品大片免费流量 | 日本免费人成在线网站 | 免费视频网站一级人爱视频 | 久草在线视频网站 |