Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
huffmanCoding/Compress.cpp
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
108 lines (82 sloc)
2.96 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Compress.H" | |
#include <fstream> | |
#include <iostream> | |
#include <vector> | |
#include <map> | |
using namespace std; | |
map<char,int> Compress::countLetters(){ | |
std::ifstream inpFile (_fname); //Will read the file | |
std::string line; | |
map<char,int> freq = map<char,int>(); | |
if (!inpFile.is_open()) throw(std::string("[Error] Could not open file " + _fname + " for countLetters() \n")); | |
//This part will count the number of occurences | |
char c; | |
while(inpFile.get(c)){ | |
freq[c]++; | |
} | |
inpFile.close(); | |
return freq; | |
} | |
void Compress::generateTree(){ | |
map<char,int> freq = countLetters(); | |
vector<shared_ptr<Node>> lst = vector<shared_ptr<Node>>(freq.size()); | |
//Add the char and its frequency into a vector | |
auto mapit = freq.begin(); | |
for (auto it = lst.begin(); it != lst.end();it++,mapit++){ | |
*it = std::make_shared<Node>(Node(mapit->second,mapit->first,NULL,NULL)); | |
} | |
while(lst.size() > 1){ //Will combine the two smallest Nodes until there is only one node | |
std::sort(lst.begin(),lst.end(),[](std::shared_ptr<Node> l1, std::shared_ptr<Node> l2)->bool{return l1->value < l2->value;}); | |
if (lst[0]->value < lst[1]->value){ | |
lst[1] = std::make_shared<Node>(Node(lst[0]->value + lst[1]->value,'\0',lst[0],lst[1])); | |
} | |
else{ | |
lst[1] = std::make_shared<Node>(Node(lst[0]->value + lst[1]->value,'\0',lst[1],lst[0])); | |
} | |
lst.erase(lst.begin()); | |
} | |
_tree = lst[0]; | |
} | |
//NEED NUMBER OF BITS FOR BODY | |
string Compress::generateBody(){ | |
ifstream inpFile(_fname); | |
if(!inpFile.is_open()) throw("[Error] Could not open file " + _fname + " for generateBody()"); | |
if (!_bitMap.size()) throw("[Error in generateBody()] _bitMap is empty"); | |
string uncompressed = ""; // Will hold binary string representation of compression | |
char c; | |
while(inpFile.get(c)){ //Adding the mapped value for each letter into the total string | |
uncompressed += _bitMap[c]; | |
} | |
inpFile.close(); | |
_counter = uncompressed.size(); | |
return convertToBits(uncompressed); | |
} | |
void Compress::compressFile(string outFile){ | |
generateTree(); | |
generateBitMap(); | |
ofstream outF(outFile); | |
if (!outF.is_open()) throw("[Error] Error accessing file " + outFile + " in compressFile\n"); | |
string body = generateBody(); | |
string header = generateHeader(); | |
outF << header + body; | |
outF.close(); | |
cout << "Compressed " + _fname + " and stored in " + outFile << endl; | |
} | |
string Compress::generateHeader(){ | |
string headerLetters = ""; | |
string tmp = preOrder(_tree,headerLetters); | |
string comp = convertToBits(tmp); | |
//# of bits in preorder / # of bits in body / preorder in bit form / letters in the preorder tree | |
return to_string(tmp.size()) + "/" + to_string(_counter) + "/" + comp + headerLetters; | |
} | |
/* | |
int main(int argc, char *argv[]){ | |
using namespace std; | |
try{ | |
shared_ptr<Compress> conv = make_shared<Compress>(Compress(argv[1])); | |
conv->compressFile("compressed_" + string(argv[1])); | |
} | |
catch(const string &e){cout << e;} | |
return 0; | |
} | |
*/ |