diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..73fafe5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +#Ignoring text Files +*.txt + +#Ignoring all .o file +*.o diff --git a/Compress.H b/Compress.H index bb47def..acd1764 100644 --- a/Compress.H +++ b/Compress.H @@ -18,6 +18,7 @@ public: void generateTree(); void compressFile(string outFile); + void printPreorder(); }; diff --git a/Compress.cpp b/Compress.cpp index 659cc1d..2900b0b 100644 --- a/Compress.cpp +++ b/Compress.cpp @@ -4,7 +4,6 @@ #include #include #include -#include using namespace std; @@ -13,19 +12,16 @@ map Compress::countLetters(){ std::string line; map freq = map(); - if (inpFile.is_open()){ - //This part will count the number of occurences - while(getline(inpFile,line)){ - for (char c : line){ - freq[c]++; - } - } - return freq; - } - else{ - throw(std::string("[Error] Could not open file " + _fname + " for countLetters() \n")); - } + 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(){ @@ -56,69 +52,65 @@ void Compress::generateTree(){ } template -string preOrder(Ptr curr){ +string preOrder(Ptr curr, string & letters){ if (curr->isLeaf()){ - return "1" + string(1,curr->letter); + letters += string(1,curr->letter); + return "1"; } - return preOrder(curr->left) + "0" + preOrder(curr->right); + return preOrder(curr->left,letters) + "0" + preOrder(curr->right,letters); } //NEED NUMBER OF BITS FOR BODY string Compress::generateBody(){ ifstream inpFile(_fname); - if(inpFile.is_open()){ - if (_bitMap.size()){ - string line; // Reads input file - string compressed = ""; // Will hold compressed body - string uncompressed = ""; // Will hold binary string representation of compression - while(getline(inpFile,line)){ - for (char c : line){ - uncompressed += _bitMap[c]; - } - } - - _counter = uncompressed.size(); - - //Start to divide the binary string into char - int index = 0; - char comp; - for (char c : uncompressed){ - if (!index){ - comp = 0x0; - } - - comp = comp | atoi(&c); - - if (index == 7){ - compressed += comp; - } - else{ - comp = comp << 1; // Shift over one bit - } - index = (index + 1) % 8; - } - - if(index){ // If body is not a multiple of 8, then the last few bits need to be copied into compressed - compressed += comp; - } - - return compressed; - } - else{ - throw("[Error in generateBody()] _bitMap is empty"); - } - } - else{ - throw("[Error] Could not open file " + _fname + " for generateBody()"); + + 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)){ + uncompressed += _bitMap[c]; } + inpFile.close(); + _counter = uncompressed.size(); +// cout << "Uncompressed string: " << uncompressed << endl; + return convertToBits(uncompressed); } void Compress::compressFile(string outFile){ + ofstream outF(outFile); + if (!outF.is_open()) throw("[Error] Error accessing file " + outFile + " in compressFile\n"); string body = generateBody(); + cout << "Size of Body compressed : " << body.length() << endl; string header = generateHeader(); - cout << header << endl << body << endl; + outF << header + body; } string Compress::generateHeader(){ - return to_string(_counter) + " " + preOrder(_tree);; + 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; +} + +void Compress::printPreorder(){ + string letts = ""; + cout << preOrder(_tree,letts) << endl; +} + + +int main(int argc, char *argv[]){ + using namespace std; + try{ + shared_ptr conv = make_shared(Compress(argv[1])); + conv->generateTree(); + conv->generateBitMap(); + conv->printPreorder(); + conv->compressFile("random"); + } + catch(const string &e){cout << e;} + return 0; } diff --git a/Huffman.H b/Huffman.H index 383456c..ea90ad5 100644 --- a/Huffman.H +++ b/Huffman.H @@ -4,6 +4,7 @@ #include #include #include +#include using namespace std; struct Node; @@ -40,4 +41,8 @@ struct Node{ bool isLeaf(){return (!left && !right);} }; +string convertToBits(string uncompressed);//Converts the string format bits into char + +string convertToString(string compressed);//Converts the bit form into string form + #endif diff --git a/Huffman.cpp b/Huffman.cpp index dcd6e58..e303b96 100644 --- a/Huffman.cpp +++ b/Huffman.cpp @@ -13,3 +13,44 @@ void Huffman::generateBitMapHelper(std::shared_ptr curr, std::string bin){ void Huffman::generateBitMap(){ //Wrapper class to recursively call enumerateTreeHelper with DFS generateBitMapHelper(_tree,""); } + +string convertToBits(string uncompressed){ //Converts the string format bits into char + string compressed = ""; + int index = 0; + char comp; + for (char c : uncompressed){ + if (!index){ + comp = 0x0; + } + + comp = comp | atoi(&c); + + if (index == 7){ + compressed += comp; + } + else{ + comp = comp << 1; // Shift over one bit + } + index = (index + 1) % 8; + } + + if(index){ // If body is not a multiple of 8, then the last few bits need to be copied into compressed + comp = comp << (7-index); + compressed += comp; + } + + return compressed; +} + +string convertToString(string compressed){//converts from binary form to string form. + string total = ""; + for (char c : compressed){ + string tmp = ""; + for (int i = 0; i < 8;i++){ + tmp = to_string(c & 0x1) + tmp; + c = c >> 1; + } + total += tmp; + } + return total; +} diff --git a/Makefile b/Makefile index 3797698..d0e9f5e 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,18 @@ -EXFILES= compress -FILES= main.o Huffman.o Compress.o +EXFILES= compress decompress +DECOMPR=Huffman.o Decompress.o +COMPR=Huffman.o Compress.o FLAGS= -std=c++14 -g -compress: $(FILES) +all: compress decompress + +fresh: clean all + +compress: $(COMPR) g++ $(FLAGS) $^ -o $@ +decompress: $(DECOMPR) + g++ $(FLAGS) $^ -o $@ + clean: -rm -f *.o $(EXFILES) diff --git a/main.cpp b/main.cpp index 53887a9..def78bd 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,6 @@ #include "Huffman.H" #include "Compress.H" +#include "Decompress.H" #include @@ -7,10 +8,15 @@ int main(int argc, char *argv[]){ using namespace std; try{ +/* shared_ptr conv = make_shared(Compress(argv[1])); conv->generateTree(); conv->generateBitMap(); conv->compressFile("random"); + cout << "String bit for A : " << convertToString("A") << endl; +*/ + Decompress tst = Decompress(argv[1]); + tst.parseText(); } catch(string &e){cout << e;} return 0;