代码拉取完成,页面将自动刷新
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include "HuffmanCompress.hpp"
#include "huffman.hpp"
#include "UseForLZ.hpp"
HuffmanCompress::HuffmanCompress() {
_status.resize(256);
for (int i = 0; i < 256; ++i) {
_status[i]._ch = i;
}
}
void HuffmanCompress::CompressFile(const string& filePath, string outPath) {
FILE* fIn = fopen(filePath.c_str(), "rb");
if (nullptr == fIn) {
std::cout << "无法打开文件" << std::endl;
return;
}
unsigned char readBuf[1024];
while (1) {
size_t size = fread(readBuf, 1, 1024, fIn);
if (0 == size) {
break;
}
for (size_t i = 0; i < size; ++i) {
_status[readBuf[i]]._appareCount++;
}
}
FreqInfo vaild;
HuffmanTree<FreqInfo> ht(_status, vaild);
//获取huffman编码
GetHuffmanCode(ht.GetRoot());
fseek(fIn, 0, SEEK_SET);
if (outPath == "") {
outPath += GetFileName(filePath);
outPath += ".huffman";
}
//打开压缩文件
FILE* fOut = fopen(outPath.c_str(), "wb");
unsigned char tmp = 0;
int tmpCnt = 0;
//压缩文件头部
//文件类型
//频次信息总行数
//文件频次信息
PutsHead(filePath, fOut);
while (1) {
size_t readSize = fread(readBuf, 1, 1024, fIn);
if (0 == readSize) break;
for (size_t i = 0; i < readSize; ++i) {
string& s = _status[readBuf[i]]._enCode;
for (size_t k = 0; k < s.size(); ++k) {
tmp <<= 1;
if ('1' == s[k]) tmp |= 1;
tmpCnt++;
if (8 == tmpCnt) {
fputc(tmp, fOut);
tmp = 0;
tmpCnt = 0;
}
}
}
}
if (tmpCnt > 0 && tmpCnt < 8) {
tmp <<= (8 - tmpCnt);
fputc(tmp, fOut);
}
fclose(fIn);
fclose(fOut);
}
void HuffmanCompress::GetHuffmanCode(HuffmanTreeNode<FreqInfo>* root) {
if (nullptr == root) {
std::cout << "编码出错" << std::endl;
return;
}
enCode(root);
}
void HuffmanCompress::enCode(HuffmanTreeNode<FreqInfo>* root) {
if (nullptr == root->_left && nullptr == root->_right) {
string& code = _status[root->_weight._ch]._enCode;
code = root->_weight._enCode;
}
if (nullptr != root->_left) {
root->_left->_weight._enCode += root->_weight._enCode + '0';
enCode(root->_left);
}
if (nullptr != root->_right) {
root->_right->_weight._enCode += root->_weight._enCode + '1';
enCode(root->_right);
}
}
void HuffmanCompress::PutsHead(const string& filePath, FILE* fOut) {
string headInfo;
//文件后缀
//headInfo += filePath;
headInfo += GetsFileTail(filePath);
headInfo += '\n';
size_t lineCnt = 0;
string tmp;
//频次信息
for (auto& i : _status) {
if (0 == i._appareCount)
continue;
tmp += i._ch;
tmp += ':';
tmp += std::to_string(i._appareCount);
tmp += '\n';
lineCnt++;
}
headInfo += std::to_string(lineCnt);
headInfo += '\n';
fwrite(headInfo.c_str(), 1, headInfo.size(), fOut);
fwrite(tmp.c_str(), 1, tmp.size(), fOut);
}
string HuffmanCompress::GetsFileTail(const string& filePath) {
return filePath.substr(filePath.find_last_of('.') + 1);
}
void HuffmanCompress::DeCmpressFile(const string& filePath, string name) {
string postfix = GetsFileTail(filePath);
if (postfix != "huffman") {
std::cout << "文件格式错误" << std::endl;
return;
}
FILE* fIn = fopen(filePath.c_str(), "rb");
if (nullptr == fIn) {
std::cout << "解压缩文件路径错误" << std::endl;
return;
}
string tmp;
GetLine(fIn, tmp);
if (name.size() == 0) {
name += GetFileName(filePath);
name += "_hfm";
name += '.';
name += tmp;
}
FILE* fOut = fopen(name.c_str(), "wb");
tmp = "";
GetLine(fIn, tmp);
size_t lineCnt = atoi(tmp.c_str());
for (int i = 0; i < lineCnt; ++i) {
tmp = "";
GetLine(fIn, tmp);
if ("" == tmp) {
tmp += '\n';
GetLine(fIn, tmp);
}
unsigned char t = tmp[0];
//放到对应位置
_status[t]._ch = t;
_status[t]._appareCount = atoi(tmp.c_str() + 2);
}
FreqInfo vaild;
HuffmanTree<FreqInfo> ht(_status, vaild);
unsigned char readBuf[1024];
HuffmanTreeNode<FreqInfo>* cur = ht.GetRoot();
size_t cnt = cur->_weight._appareCount;
while (1) {
size_t size = fread(readBuf, 1, 1024, fIn);
if (0 == size) {
break;
}
//std::cout << size << std::endl;
for (size_t i = 0; i < size; ++i) {
char ch = readBuf[i];
for (int k = 0; k < 8; ++k) {
if (ch & 0x80) cur = cur->_right;
else cur = cur->_left;
ch <<= 1;
if (nullptr == cur->_left && nullptr == cur->_right) {
fputc(cur->_weight._ch, fOut);
cur = ht.GetRoot();
--cnt;
if (!cnt) break;
}
}
}
}
fclose(fIn);
fclose(fOut);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。