1 Star 0 Fork 1

炫炫的嗅嗅/GZip文件压缩

forked from pppsh/GZip文件压缩 
Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Please pay attention to the specific project description and its upstream code dependency when using it.
Clone or Download
HuffmanCompress.cpp 4.30 KB
Copy Edit Raw Blame History
pppsh authored 2022-09-05 20:18 . gzip文件压缩
#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);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/lianchen5/gzip-file-compression.git
git@gitee.com:lianchen5/gzip-file-compression.git
lianchen5
gzip-file-compression
GZip文件压缩
master

Search