c++实现哈夫曼编码压缩文件内容并解压
时间: 2023-08-07 18:54:55 浏览: 268
要实现哈夫曼编码的文件压缩和解压缩,需要对文件进行读取和写入操作。下面是一个示例代码,展示了如何使用C++实现哈夫曼编码的文件压缩和解压缩:
```cpp
#include <iostream>
#include <fstream>
#include <queue>
#include <unordered_map>
using namespace std;
// 哈夫曼树节点
struct HuffmanNode {
char data;
int freq;
HuffmanNode* left;
HuffmanNode* right;
HuffmanNode(char data, int freq) {
this->data = data;
this->freq = freq;
left = right = nullptr;
}
};
// 比较器,用于优先队列排序
struct Compare {
bool operator()(HuffmanNode* a, HuffmanNode* b) {
return a->freq > b->freq;
}
};
// 构建哈夫曼树
HuffmanNode* buildHuffmanTree(const unordered_map<char, int>& freqMap) {
priority_queue<HuffmanNode*, vector<HuffmanNode*>, Compare> pq;
for (auto& pair : freqMap) {
pq.push(new HuffmanNode(pair.first, pair.second));
}
while (pq.size() > 1) {
HuffmanNode* left = pq.top();
pq.pop();
HuffmanNode* right = pq.top();
pq.pop();
HuffmanNode* newNode = new HuffmanNode('#', left->freq + right->freq);
newNode->left = left;
newNode->right = right;
pq.push(newNode);
}
return pq.top();
}
// 构建哈夫曼编码表
void buildHuffmanCodes(HuffmanNode* root, string code, unordered_map<char, string>& codes) {
if (root == nullptr) {
return;
}
if (root->left == nullptr && root->right == nullptr) {
codes[root->data] = code;
}
buildHuffmanCodes(root->left, code + "0", codes);
buildHuffmanCodes(root->right, code + "1", codes);
}
// 将字符转换为字符串
string charToString(char c) {
string result;
for (int i = 0; i < 8; i++) {
result += (c & (1 << (7 - i))) ? '1' : '0';
}
return result;
}
// 将字符串转换为字符
char stringToChar(const string& str) {
char result = 0;
for (int i = 0; i < 8; i++) {
if (str[i] == '1') {
result |= 1 << (7 - i);
}
}
return result;
}
// 哈夫曼编码压缩文件
void compressFile(const string& inputFile, const string& outputFile) {
// 读取输入文件
ifstream ifs(inputFile, ios::binary);
if (!ifs) {
cout << "Error opening input file!" << endl;
return;
}
// 统计字符频率
unordered_map<char, int> freqMap;
char c;
while (ifs.get(c)) {
freqMap[c]++;
}
ifs.close();
// 构建哈夫曼树和编码表
HuffmanNode* root = buildHuffmanTree(freqMap);
unordered_map<char, string> codes;
buildHuffmanCodes(root, "", codes);
// 写入压缩后的文件
ifs.open(inputFile, ios::binary);
ofstream ofs(outputFile, ios::binary);
string compressedText;
while (ifs.get(c)) {
compressedText += codes[c];
while (compressedText.length() >= 8) {
ofs << stringToChar(compressedText.substr(0, 8));
compressedText = compressedText.substr(8);
}
}
ifs.close();
// 写入最后一个字节的编码
if (!compressedText.empty()) {
while (compressedText.length() < 8) {
compressedText += '0';
}
ofs << stringToChar(compressedText);
}
ofs.close();
}
// 哈夫曼解压缩文件
void decompressFile(const string& inputFile, const string& outputFile) {
// 读取输入文件
ifstream ifs(inputFile, ios::binary);
if (!ifs) {
cout << "Error opening input file!" << endl;
return;
}
// 读取哈夫曼编码表
unordered_map<string, char> reverseCodes;
string line;
while (getline(ifs, line)) {
if (line.empty()) {
break;
}
char c = line[0];
reverseCodes[line.substr(2)] = c;
}
// 解压缩文件
ofstream ofs(outputFile, ios::binary);
string compressedText, code;
char c;
while (ifs.get(c)) {
compressedText += charToString(c);
for (char bit : compressedText) {
code += bit;
if (reverseCodes.find(code) != reverseCodes.end()) {
ofs << reverseCodes[code];
code = "";
}
}
compressedText = compressedText.substr(code.length());
}
ofs.close();
ifs.close();
}
// 测试示例
int main() {
string inputFile = "input.txt";
string compressedFile = "compressed.bin";
string decompressedFile = "decompressed.txt";
// 哈夫曼编码压缩文件
compressFile(inputFile, compressedFile);
cout << "File compressed successfully!" << endl;
// 哈夫曼解压缩文件
decompressFile(compressedFile, decompressedFile);
cout << "File decompressed successfully!" << endl;
return 0;
}
```
上述代码中,`compressFile`函数用于将输入文件压缩为二进制文件,`decompressFile`函数用于将压缩的二进制文件解压缩为文本文件。在压缩过程中,首先统计字符频率,然后构建哈夫曼树和编码表,并将编码后的数据写入压缩文件。在解压缩过程中,读取哈夫曼编码表,然后根据编码表将压缩的二进制数据解码为原始文本,并写入解压缩文件。
请注意,在使用时需要将`input.txt`替换为要压缩的输入文件的路径,`compressed.bin`替换为压缩后的二进制文件的路径,`decompressed.txt`替换为解压缩后的文本文件的路径。
希望对你有所帮助!
阅读全文