成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

文件壓縮與解壓-創(chuàng)新互聯(lián)

文件的壓縮與解壓

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)高明免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了1000+企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

開發(fā)環(huán)境:vs2013

開發(fā)技術(shù):vector、堆、哈夫曼樹、文件部分函數(shù)的操作

項(xiàng)目描述:文件壓縮是把一個(gè)占內(nèi)存比較大的文件壓縮成為一個(gè)占內(nèi)存比較小的文件,節(jié)省了磁盤的空                間,傳輸時(shí)也比較方便。解壓是把壓縮的文件還原成原來的文件,讀寫比較方便。

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

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

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

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

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

                  √ 有時(shí)讀大文件時(shí),會讀不全。因此我就把EOF換成了feof。因?yàn)镋OF是以-1為結(jié)束標(biāo)志                       的,但文件中出現(xiàn)-1它就不會讀下去了。如果換成feof的話,它是以“文件結(jié)束”為標(biāo)                       志。這樣就不會出現(xiàn)讀不完的情況。

compress.h中

#ifndef __Compress_H_
#define __Compress_H_

#include <string>
typedef long long LongType;

struct CharInfo
{
	unsigned char _ch;//字符
	LongType _count;//出現(xiàn)次數(shù)
	string _code;//哈夫曼編碼
	CharInfo(unsigned char ch = '0')
		:_ch(ch)
		, _count(0)
		, _code("")
	{}
	CharInfo(LongType count)
		:_count(count)
		, _ch(0)
		, _code("")
	{}
	//重載運(yùn)算符“>”
	bool operator >(const CharInfo& com)const
	{
		return _count > com._count;
	}
	//重載運(yùn)算符“!=”
	bool operator !=(CharInfo com)const 
	{
		return _count != com._count;
	}
	//重載運(yùn)算符“+”
	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);
		//統(tǒng)計(jì)每個(gè)字符出現(xiàn)的次數(shù)
		ch = fgetc(fout);
		while (!feof(fout))
		{
			_info[(unsigned char)ch]._count++;
			ch = fgetc(fout);
		}
		//用次數(shù)建立哈夫曼樹
		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;//標(biāo)記當(dāng)前位
		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個(gè)字節(jié),將其寫入到壓縮文件中
				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);
		//將字符的總個(gè)數(shù)寫進(jìn)配置文件
		char infostr[32];
		//將出現(xiàn)的字符以及次數(shù)寫進(jìn)配置文件
		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;
		//字符出現(xiàn)的次數(shù)
		while (ReadLine(fout, tmp))
		{
			if (!tmp.empty())
			{
				//那到字符
				ch = tmp[0];
				//獲取字符的次數(shù)
				_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);
		//根據(jù)壓縮文件,還原文件
		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);//寫進(jìn)解壓文件
				cur = root;
			}
			--len;
		}
		fclose(fout);
		fclose(fin);
		fclose(fcom);
	}
protected:
	//創(chuàng)建哈夫曼編碼
	void _CreateHaffmanCode(HaffmanTreeNode<CharInfo>*root, string tmp)
	{
		//判空
		if (root == NULL)
		{
			return;
		}
		if (root->_left == NULL&&root->_right == NULL)
		{
			//找到下標(biāo),把編碼寫到_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);
	}
	//構(gòu)造函數(shù)
	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:
	//創(chuàng)建哈夫曼樹
	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);
			}
		}
		//構(gòu)造哈夫曼樹
		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();
	}
	//釋放節(jié)點(diǎn)
	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:
	//構(gòu)造函數(shù)
	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--;         
		}
	}
	//拷貝構(gòu)造
	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:
	//下調(diào)
	void _AdjustDown(int parent)
	{ // 從根節(jié)點(diǎn)向下調(diào)整
		int size = _arr.size();
		int left = parent * 2 + 1;
		int right = left + 1;
		int key = left;
		while (left < size)
		{//Compare()仿函數(shù)
			//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;
		}
	}
	//上調(diào)
	void _AdjustUp(int child)
	{  //從葉子節(jié)點(diǎn)或子節(jié)點(diǎn)向上調(diào)整
		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("壓縮文件需要的時(shí)間: %f s \n", t1 / CLOCKS_PER_SEC);
	//f.UnCompress("input.txt");
	f.UnCompress("mnt.txt");
	t2 = clock();
	printf("解壓縮文件需要的時(shí)間: %f s \n", t2 / CLOCKS_PER_SEC);
}
int main()
{
	Test();
	system("pause");
	return 0;
}

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

網(wǎng)站題目:文件壓縮與解壓-創(chuàng)新互聯(lián)
文章源于:http://jinyejixie.com/article28/dipejp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、Google、企業(yè)建站、全網(wǎng)營銷推廣、軟件開發(fā)、手機(jī)網(wǎng)站建設(shè)

廣告

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

微信小程序開發(fā)
金寨县| 玛纳斯县| 青浦区| 双城市| 安仁县| 沈阳市| 涿鹿县| 和平区| 焉耆| 岚皋县| 普宁市| 高尔夫| 屯昌县| 东城区| 菏泽市| 雷山县| 二连浩特市| 昌都县| 论坛| 嘉荫县| 衡东县| 大方县| 河间市| 永和县| 肇州县| 潞城市| 泰州市| 社会| 丹阳市| 二手房| 伊金霍洛旗| 哈尔滨市| 郁南县| 文水县| 威远县| 双桥区| 淮北市| 育儿| 洛阳市| 穆棱市| 万山特区|