diff --git a/.gitignore b/.gitignore index fed3380..4a5aac3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,5 @@ random *.swp #ignore executables -compress -decompress - +huffman diff --git a/Compress.cpp b/Compress.cpp index 04a3a53..185829c 100644 --- a/Compress.cpp +++ b/Compress.cpp @@ -62,23 +62,29 @@ string Compress::generateBody(){ string uncompressed = ""; // Will hold binary string representation of compression char c; - while(inpFile.get(c)){ + while(inpFile.get(c)){ //Adding the mapped value for each letter into the total string uncompressed += _bitMap[c]; } - cout <<"UncomPressed binary: " << uncompressed << endl; + inpFile.close(); + _counter = uncompressed.size(); -// cout << "Uncompressed string: " << uncompressed << endl; + 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(); - cout << "Size of Body compressed : " << body.length() << endl; string header = generateHeader(); outF << header + body; + outF.close(); + + cout << "Compressed " + _fname + " and stored in " + outFile << endl; } string Compress::generateHeader(){ @@ -89,15 +95,14 @@ string Compress::generateHeader(){ return to_string(tmp.size()) + "/" + to_string(_counter) + "/" + comp + headerLetters; } +/* 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"); + conv->compressFile("compressed_" + string(argv[1])); } catch(const string &e){cout << e;} return 0; } +*/ diff --git a/Decompress.H b/Decompress.H index be65d84..bee0fc6 100644 --- a/Decompress.H +++ b/Decompress.H @@ -8,29 +8,29 @@ using namespace std; -struct FileParse; +struct Header; class Decompress : public Huffman { - shared_ptr _header; // Will hold parse Compressed file info + shared_ptr
_header; // Will hold parse Compressed file info shared_ptr generateTreeHelper(string& bin); void parseText(); void generateTree(); public: Decompress(string fname): Huffman(fname){} - void decompressFile(); + void decompressFile(string output); }; -struct FileParse{ +struct Header{ int bodySize; - int headerSize; + int preorderSize; string preorderStr; queue letters; string body; - FileParse(){} - ~FileParse(){} + Header(){} + ~Header(){} }; #endif diff --git a/Decompress.cpp b/Decompress.cpp index dfaf200..393a0d6 100644 --- a/Decompress.cpp +++ b/Decompress.cpp @@ -15,7 +15,8 @@ void Decompress::parseText(){ throw("[Error] Could not open file " + _fname + " in parseText()\n"); } - _header = make_shared(FileParse()); + _header = make_shared
(Header()); + char c; string val; @@ -23,9 +24,7 @@ void Decompress::parseText(){ while(inpFile.get(c) && c != '/'){ val += string(1,c); } - _header->headerSize = stoi(val); - - cout << "Passed Parsing\n" << endl; + _header->preorderSize = stoi(val); //Retrieve Body Size val = ""; @@ -36,12 +35,12 @@ void Decompress::parseText(){ //Getting PreOrder String val = ""; - for (int i = 0; i < ceil((_header->headerSize)/8.0);i++){ + for (int i = 0; i < ceil((_header->preorderSize)/8.0);i++){ val += inpFile.get(); } _header->preorderStr = convertToString(val); - _header->preorderStr = string(_header->preorderStr.begin(),_header->preorderStr.begin()+_header->headerSize); + _header->preorderStr = string(_header->preorderStr.begin(),_header->preorderStr.begin()+_header->preorderSize); //Getting Letters for each leaf in Tree int counter = 0; @@ -71,9 +70,11 @@ shared_ptr Decompress::generateTreeHelper(string& bin){ if (bin.size() < 1){ return NULL; } + string bit = string(bin.begin(),bin.begin()+1); // First element in string bin = string(bin.begin()+1,bin.end()); //The rest of the string shared_ptr curr; + if (!bit.compare("1")){ curr = make_shared(Node(0,_header->letters.front(),NULL,NULL)); _header->letters.pop(); @@ -84,7 +85,7 @@ shared_ptr Decompress::generateTreeHelper(string& bin){ return curr; } -void Decompress::decompressFile(){ +void Decompress::decompressFile(string output){ parseText(); generateTree(); generateBitMap(); @@ -99,24 +100,26 @@ void Decompress::decompressFile(){ curr = _tree; } } - cout << "uncompressed: " << uncompress << endl; -} + ofstream outFile(output); + + if (!outFile.is_open()) throw("[Error] Could not open filename " + output + "in decompressFile()\n"); + + outFile << uncompress; + outFile.close(); + cout << "Decompressed " + _fname + " and saved to " + output << endl; +} +/* 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.decompressFile(); tst.printPreorder(); } catch(string &e){cout << e;} return 0; } +*/ diff --git a/Huffman.cpp b/Huffman.cpp index 75a470f..4b96f25 100644 --- a/Huffman.cpp +++ b/Huffman.cpp @@ -14,7 +14,6 @@ void Huffman::generateBitMapHelper(std::shared_ptr curr, std::string bin){ void Huffman::generateBitMap(){ //Wrapper class to recursively call enumerateTreeHelper with DFS generateBitMapHelper(_tree,""); - printBitMap(); } void Huffman::printBitMap(){ diff --git a/Makefile b/Makefile index d0e9f5e..34a0e4c 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,20 @@ EXFILES= compress decompress -DECOMPR=Huffman.o Decompress.o -COMPR=Huffman.o Compress.o +HUFFMAN= Huffman.o Compress.o Decompress.o main.o FLAGS= -std=c++14 -g -all: compress decompress +all: huffman fresh: clean all -compress: $(COMPR) - g++ $(FLAGS) $^ -o $@ - -decompress: $(DECOMPR) +huffman: $(HUFFMAN) g++ $(FLAGS) $^ -o $@ +#compress: $(COMPR) +# g++ $(FLAGS) $^ -o $@ + +#decompress: $(DECOMPR) +# g++ $(FLAGS) $^ -o $@ + clean: -rm -f *.o $(EXFILES) diff --git a/main.cpp b/main.cpp index def78bd..d33afa0 100644 --- a/main.cpp +++ b/main.cpp @@ -3,21 +3,85 @@ #include "Decompress.H" #include +#include +#include +#include + +using namespace std; + + +void printIntroduction(){ + cout << "Huffman base Data Compression (Lossless)\n" + << "Written By: Tony Pham\n" + << "Version: 1.0.0.0.0..........\n"; +} + +void printInstruction(){ + cout << "[Usage] ./huffman <-d/-c> \n" + << " - If an output filename is not given:\n" + << "\t - Compressing (-c): the output will be the input name appended with 'compressed_'\n" + << "\t - Decompressing (-d): the output will be the input name appended with 'decompressed_'\n" + << " - To check program version use the tag --v\n"; +} + +void parseInput(vector input){ + + if(input.size() < 2){ // Not enough given args + cout << "Not enough arguments" << endl; + return; + } + if (!(input.at(0).compare("-c"))){ + Compress comp = Compress(input.at(1)); + if (input.size() < 3) comp.compressFile("compressed_"+input.at(1)); + else comp.compressFile(input.at(2)); + } + else if (!(input.at(0).compare("-d"))){ + Decompress decomp = Decompress(input.at(1)); + if(input.size() < 3){ + string str = input.at(1); + size_t found = str.find("_"); + string check = string(str.begin(),str.begin()+found+1); + if (!check.compare("compressed_")) decomp.decompressFile("de"+input.at(1)); + else decomp.decompressFile("decompressed_"+input.at(1)); + } + else { decomp.decompressFile(input.at(2));} + } + else{ + cout << input.at(0) + " is not a recognized command\n"; + } +} 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;} + if (argc < 2){ + cout << "[Usage] ./huffman <-d/-c> \n \t For more information run the progam with -h\n"; + exit(0); + } + + if (!strcmp(argv[1],"--v")){ + printIntroduction(); + exit(0); + } + + if (!strcmp(argv[1],"-h")){ + printInstruction(); + exit(0); + } + + if (argc > 2){ + vector input = vector(); + input.push_back(string(argv[1])); + input.push_back(string(argv[2])); + if (argc > 3) input.push_back(argv[3]); + try{ + parseInput(input); + } + catch(string &e){cout << e << endl;} + } + else{ + cout << "Unknown Command: " + string(argv[1]) + "\n"; + } + return 0; }