文件压缩程序的设计与实现的代码C++
时间: 2023-12-29 10:50:01 浏览: 31
以下是一个简单的文件压缩程序的设计与实现的 C++ 代码,仅供参考:
```c++
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <queue>
#include <bitset>
using namespace std;
// 定义每个字符的统计信息
struct CharInfo {
int freq;
CharInfo* left;
CharInfo* right;
CharInfo(int f = 0) : freq(f), left(nullptr), right(nullptr) {}
// 定义小于操作符,用于优先队列排序
bool operator<(const CharInfo& other) const {
return freq > other.freq;
}
};
// 统计文件中每个字符出现的频率
void countCharFreq(const string& fileName, map<char, int>& freqMap) {
ifstream ifs(fileName);
if (!ifs) {
cerr << "Failed to open file " << fileName << endl;
exit(1);
}
char c;
while (ifs.get(c)) {
// 将字符加入频率表中
freqMap[c]++;
}
ifs.close();
}
// 用哈夫曼树压缩文件
void compressFile(const string& inputFileName, const string& outputFileName,
const map<char, string>& codeMap, const int totalBits) {
ifstream ifs(inputFileName);
if (!ifs) {
cerr << "Failed to open file " << inputFileName << endl;
exit(1);
}
ofstream ofs(outputFileName, ios::binary);
if (!ofs) {
cerr << "Failed to create file " << outputFileName << endl;
exit(1);
}
// 文件头部写入总位数
ofs.write(reinterpret_cast<const char*>(&totalBits), sizeof(totalBits));
string buffer;
char c;
while (ifs.get(c)) {
// 将字符的编码加入缓冲区
buffer += codeMap.at(c);
while (buffer.size() >= 8) {
// 将缓冲区中8个字符转换为一个字节写入输出文件中
bitset<8> bits(buffer.substr(0, 8));
ofs.write(reinterpret_cast<const char*>(&bits), sizeof(bits));
buffer = buffer.substr(8);
}
}
// 处理剩余字符
if (!buffer.empty()) {
buffer += string(8 - buffer.size(), '0');
bitset<8> bits(buffer);
ofs.write(reinterpret_cast<const char*>(&bits), sizeof(bits));
}
ifs.close();
ofs.close();
}
int main(int argc, char* argv[]) {
if (argc != 3) {
cerr << "Usage: " << argv[0] << " <input_file> <output_file>" << endl;
return 1;
}
// 统计每个字符出现的频率
map<char, int> freqMap;
countCharFreq(argv[1], freqMap);
// 构建哈夫曼树
priority_queue<CharInfo> pq;
for (const auto& p : freqMap) {
pq.push(CharInfo(p.second));
}
while (pq.size() > 1) {
CharInfo* left = new CharInfo(pq.top().freq);
left->left = pq.top().left;
left->right = pq.top().right;
pq.pop();
CharInfo* right = new CharInfo(pq.top().freq);
right->left = pq.top().left;
right->right = pq.top().right;
pq.pop();
pq.push(CharInfo(left->freq + right->freq));
}
// 生成每个字符的编码
map<char, string> codeMap;
if (!pq.empty()) {
string code;
CharInfo* root = new CharInfo(pq.top().freq);
root->left = pq.top().left;
root->right = pq.top().right;
function<void(CharInfo*, string)> dfs = [&](CharInfo* node, string code) {
if (!node) {
return;
}
if (node->left == nullptr && node->right == nullptr) {
codeMap[node->freq] = code;
return;
}
dfs(node->left, code + "0");
dfs(node->right, code + "1");
};
dfs(root, "");
}
// 压缩文件
compressFile(argv[1], argv[2], codeMap, codeMap.size() * 8);
return 0;
}
```