Compression and decompression of files
u Development Environment : vs2013
u :
u : File compression is to compress a large memory file into a small memory file, saving disk space &N Bsp , transmission is also more convenient. Decompression is to restore the compressed file into the original file, read and write more convenient.
√ can compress and unzip small files, can also compress and unzip large files.
√ In the debug, compression and decompression of about 6M files, need about 25s, in the release, need 2s or so.
&N Bsp √ has profiles, compression vector,
u problems encountered :√ in the compression process not enough 8 bits will be 0, but in the decompression process will be zero read out, so it is wrong. To resolve &NBSP ; The problem. I defined a total length in the decompression process, it writes a character, the total length is reduced by 1, when the length &NB Sp minus 0, don't go in.
' \r ' but with binary mode it won't have this issues.
√ Sometimes read a large file, you will not read it all. So I swapped EOF for feof. Because EOF is the end flag with-1, but it appears in the file-1 it will not be read anymore. If you switch to feof, it is marked with "End of file". This will not be able to read an endless situation.
In Compress.h
#ifndef __compress_h_#define __compress_h_#include <string>typedef long long longtype;struct charinfo{unsigned char _ch;//character longtype _count;//occurrences string _ code;//Huffman Code charinfo (unsigned char ch = ' 0 '): _ch (CH), _count (0), _code ("") {} Charinfo (Longtype count): _count (count), _ch (0), _code ("") {}//overloaded operator > "Bool operator > (const charinfo& com) Const{return _count > com._count;} Overloaded operator "! =" bool operator != (charinfo com) const {return _count != com._count ;} Overloaded operator "+" charinfo operator+ (const charinfo& com) const{return charinfo (_count + com._count);}}; class filecompress{public://compression filecompress () {for (size_t i = 0; i < 256; i++) {_info[i]._ch = i;}} Void compress (const char* file) {//Read file file *fout = fopen (file, "RB"); Unsigned char ch = 0;assert (fout);//Count the occurrences of each character ch = fgetc (fout);while (!feof (fout)) {_info[(Unsigned char) ch]._count++;ch = fgetc (fout);} Using the number of times to establish Huffman Tree Const charinfo invalid ((unsigned char) 0); Haffmantree<charinfo> tree (_info, 256,invalid);//Generate Huffman Code String tmp;_createhaffmancode ( Tree. Getroot (), tmp);//Compressed fseek (Fout, 0, seek_set);//compressed/Compressed file name starting from the first character of the document String comfile = file;comfile += ". Haffman"; File *fin = fopen (Comfile.c_str (), "WB"); assert (Fin); unsigned char value = 0;size_t index = 0;//Mark Current bit 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;} Over 8Byte, writes it to the compressed file if (++index == 8) {FPUTC (value, fin); value = 0; index = 0;}} CH&NBSP;=&NBSP;FGETC (fout);} If the,value is not written to 8 bits, the remaining press into the compressed file if (index != 0) {value <<= (8 - index); FPUTC (Value, fin);} Configuration file string configfile = file;configfile += ". config"; File* finfo = fopen (Configfile.c_str (), "WB"), assert (Finfo);//write the total number of characters into the configuration file char infostr[32];//writes the occurrences of the characters and the number of times into the configuration file 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);} Unzip Void uncompress (const char *file) {UNSIGNED&NBSP;CHAR&NBSP;CH&Nbsp;= 0;string fconfig = file;fconfig += ". config";//Read Compressed file file* fout = fopen (Fconfig.c_str (), "RB"), assert (Fout), string tmp;//character occurrences while (ReadLine (fout, TMP)) {if (!tmp.empty ()) {//That to character ch = tmp[0];//gets the number of characters _info[(Unsigned char) ch]._count = atoi (TMP.SUBSTR (2). C_STR ()); Tmp.clear (); else{tmp = ' \ n ';}} Rebuilding Huffman Tree Charinfo invalid ((unsigned char) 0); Haffmantree<charinfo> h (_info, 256, invalid); Haffmantreenode<charinfo>*root = h.getroot ();//Decompression String output = file;output += ". uncom"; File* fin = fopen (Output.c_str (), "WB"); assert (Fin);//Restore files based on compressed files String haffmanfile = file; haffmanfile += ". Haffman"; File* fcom = fopen (Haffmanfile.c_str (), "RB"); assert (fcom); HAFFMANTREENODE<CHARINFO>*CUR&NBSP;=&NBSP;ROOT;CH&NBSP;=&NBSP;FGETC (fcom); int pos = 8; longtype len = root->_weight._count;while (len > 0) {while (cur->_ Left &&cur->_right) {if (pos == 0) {ch = fgetc (fcom);p os = 8;} --pos;//with 1, walk right Tree if (ch& (1 << pos)) {cur = cur->_right;} With 0, walk left tree Else{cur = cur->_left;}} if (cur) {FPUTC (Cur->_weight._ch, fin);//write in unzip file cur = root;} --len;} Fclose (Fout); fclose (Fin); fclose (fcom);} PROTECTED://Create Huffman Code Void _createhaffmancode (haffmantreenode<charinfo>*root, string tmp) {// Empty if (Root == null) {return;} if (root->_left == null&&root->_right == null) {//find subscript, write code to _code int index = (root->_weight). _ch;_info[index]._code = tmp;} else{//Zo Shu Write 0if (root->_left) {tmp.push_back (' 0 '); _createhaffmancode (root->_left, tmp); tmp.pop_ Back ();} Right tree write 1if (root->_right) {tmp.push_back (' 1 '); _createHaffmancode (root->_right, tmp); Tmp.pop_back ();}} Reads a line 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 in
#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);} Constructor 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://Create Huffman Tree node* _create (const t* arr, size_t size, const t& invalid) {&NBSP;STRUCT&NBSP;COMPARE{BOOL&NBSP;OPERATOR&NBSP; () (Const node *left, const node *right) {return left->_weight > right->_weight;}}; heap<node*,compare> _heap;//put the value in the vector for (size_t i = 0; i < size; ++i) {if (arr[i] != invalid) {Node *tmp = new node (arr[i ]); _heap. Push (TMP);}} Construct Huffman Tree while (_heap. Size () > 1) {node *left = _heap. Top (); _heap. Pop (); Node*right = _heap. Top (); _heap. Pop (); Node *parent = new node (left->_weight + right->_weight);p Arent->_left = left;parent->_right = right;_heap. Push (parent); Return _heap. Top ();} Release node 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_
In Heap.h
#ifndef __Heap_H_#define __Heap_H_#include<vector> #include <assert.h>template<class t>//Comparator 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:// Constructor 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--; }}//copy construction 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) { // downward adjustment from the root node int size = _arr.size ();int left = parent * 2 + 1;int right = left + 1; int key = left;while (left < size) {//compare () functor//if (right < size &amP;& array[left] > array[right]) if (right < size && Compare () (_arr[left], _arr[right])) //right small {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]) //left small {swap (_arr[key], _arr[parent]);} parent = key;left = parent * 2 + 1;right = left + 1;}} Raise Void _adjustup (Int child) { //to adjust the int size = _arr.size () upward from the leaf node or child node; (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_
In 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 ();p rintf ("Time required for compressed files:%f s \ n", T1/clocks_ PER_SEC);//f.uncompress ("Input.txt"); F.uncompress ("Mnt.txt"); t2 = Clock ();p rintf ("Time required for extracting files:%f s \ n", T2/clocks_ PER_SEC);} int main () {Test (); System ("pause"); return 0;}
File compression and decompression