string HuffmanEncoder::decodeBits(vector<bool> bits, vector<string> huffmanMap) { HuffmanTree *tree = HuffmanEncoder::huffmanTreeFromMap(huffmanMap); vector<string> map = HuffmanEncoder::huffmanEncodingMapFromTree(tree); HuffmanEncoder::writeEncodingMapToFile(map, "encmap.map"); HuffmanNode *n = tree->GetRoot(); ostringstream result{}; uint64_t last_index = 0; string stack; int num_decoded = 0; //tree->Print(); for (auto it = bits.begin(); it != bits.end(); ++it) { bool bit = *it; if (bit == false) { stack += "0"; n = ((HuffmanInternalNode*)n)->GetLeftChild(); } else { stack += "1"; n = ((HuffmanInternalNode*)n)->GetRightChild(); } if (n->IsLeaf()) { result << ((HuffmanLeafNode*)n)->GetValue(); num_decoded++; n = tree->GetRoot(); stack = ""; } last_index++; } /* TODO: perhaps the priority queue is different for each? That might * explain it. Compare frequencies, that can't be wrong. Issue is we have * different huffman maps on each run. Although, that might not be a problem * on write. The files are slightly different, make sure it's writing to a * good offset. Maybe try writing/reading garbage from that spot or * something, print out the first few chars, idk. Print where the offsets * and such are. Figure out exactly what is going where and if the way it's * getting compressed/decompressed differently is a problem. */ return result.str(); }
HuffmanTree* HuffmanEncoder::huffmanTreeFromMap(vector<string> huffmanMap) { //Generates a Huffman Tree based on the supplied Huffman Map.Recall that a //Huffman Map contains a series of codes(e.g. 'a' = > 001).Each digit(0, 1) //in a given code corresponds to a left branch for 0 and right branch for 1. HuffmanTree *tree = new HuffmanTree(new HuffmanInternalNode(NULL, NULL)); for (int i = 0; i < 256; i++) { char c = (char) i; string code = huffmanMap[i]; if (code.length() == 0) continue; HuffmanInternalNode *n = (HuffmanInternalNode*)tree->GetRoot(); for (unsigned int j = 0; j < code.length() -1; ++j) { if (code[j] == '0') { if (n->GetLeftChild() != NULL) { n = (HuffmanInternalNode*) n->GetLeftChild(); } else { n->SetLeftChild(new HuffmanInternalNode(NULL, NULL)); n = (HuffmanInternalNode*) n->GetLeftChild(); } } else { if (n->GetRightChild() != NULL) { if (n->IsLeaf()) { //tree->Print(); exit(1); } n = (HuffmanInternalNode*) n->GetRightChild(); } else { n->SetRightChild(new HuffmanInternalNode(NULL, NULL)); n = (HuffmanInternalNode*) n->GetRightChild(); } } } c = code[code.length() -1]; if (c == '0') { n->SetLeftChild(new HuffmanLeafNode((char)i, 0)); } else { n->SetRightChild(new HuffmanLeafNode((char)i, 0)); } } //printf("Tree created from map:\n"); //tree->Print(); return tree; }
void FileCompress::Uncompress(const char* filename) { HuffmanTree ht; int size = 0; //从配置文件中获取字符信息 string filenameconfig = filename; filenameconfig += ".config"; FILE* fout = fopen(filenameconfig.c_str(),"r"); assert(fout); unsigned char ch = fgetc(fout); long long sum = 0; while (!feof(fout)) { _infos[ch]._ch = ch; size++; char num = fgetc(fout); num = fgetc(fout); _infos[ch]._count = num - '0'; sum += _infos[ch]._count; ch = fgetc(fout); ch = fgetc(fout); } fclose(fout); //建树 CharInfo invaild; //ReadConfig(filename, _infos); ht.CreateTree(_infos, size,invaild); //从压缩文件取值遍历 string filenamecom = filename; filenamecom += ".com"; FILE* fin = fopen(filenamecom.c_str(),"r"); assert(fin); string filenameuncom = filename; filenameuncom += ".uncom"; fout = fopen(filenameuncom.c_str(), "w"); assert(fout); HuffmanTreeNode<CharInfo>* temp = ht.GetRoot(); ch = fgetc(fin); int count = 0; unsigned int t = 1; while ( !feof(fin))//sum != 0) { int x = 0; for (int i = 7; i >= 0; i--) { x = ch & (t << 7); if ((char)ch == EOF) { cout << 1; } ch <<= 1; if (x == 0) temp = temp->_left; else if (x == 0x80) temp = temp->_right; if (temp->_left == NULL && temp->_right == NULL) { fputc(temp->_weight._ch, fout); //sum--; cout << temp->_weight._ch; temp = ht.GetRoot(); x = 0; } } ch = fgetc(fin); } fclose(fin); fclose(fout); }
void FileCompress::Compress(const char* filename) { HuffmanTree mh; int size = Get_infos_Com(filename); //建树 CharInfo invaild; mh.CreateTree(_infos, size,invaild); //编码 string code; GenerateHuffmanCode(mh.GetRoot(), code); //配置文件 string filenameConfig = filename; filenameConfig += ".config"; FILE* fout = fopen(filenameConfig.c_str(), "wb"); assert(fout); for (int i = 0; i < 256; i++) { if (_infos[i]._count != 0) { fputc(_infos[i]._ch, fout); fputc(',', fout); fputc(_infos[i]._count+'0',fout); fputc('\n',fout); } } fclose(fout); //WriteConfig(filename); FILE* fin = fopen(filename, "r"); unsigned char ch = fgetc(fin); string filenamecom = filename; filenamecom += ".com"; fout = fopen(filenamecom.c_str(), "w+"); assert(fout); unsigned char value = 0; int pos = 7; while (!feof(fin)) { if (ch == '\r') { ch = fgetc(fout); if (ch != '\n') { fseek(fout, -1, SEEK_CUR); } } string& code = _infos[ch].code; int d = 0; for (int i = 0; i < code.size(); i++) { value <<= 1; if ((code[i] - '0') & (1)) { value |= 1; } else { value |= 0; d = 1; } pos--; if (pos == -1) { fputc(value, fout); if (d = 0) { cout << 1; } value = 0; d = 0; pos = 7; } } ch = fgetc(fin); } if (pos != -1) { for (int i = 0; i <= pos; i++) { value <<= 1; } fputc(value, fout); } fclose(fin); fclose(fout); }