LZW解压c++
LZW Decompression c++
我正在尝试对 lzw 数据进行编码 compressor/decompressor,br/>
所以我确实使用 this Algorithm 制作了一个压缩器(它似乎可以工作但也许不工作)但是当我尝试解压缩它时,我得到一个奇怪的结果,看起来完全不像原始文件...
我认为我的错误在于我从文件中获取 and/or 使用数据的方式,但我不确定......所以这是我用来压缩和解压缩的功能,当然欢迎任何评论/问题。
编辑:给一个 MCVE
正在压缩的输入文本文件包含:banana_bandana
解压输出结果:ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ #ü#ìû#ÿ#ü#ìû#ÿ#ü#
编辑 2:重现输出的所有有用功能:
using Encoding = uint16_t;
#define MAX 4096 //2^12
static int code = 0;
string combi (string s , char c ){
s += c ;
return s;
}
string findkey(unordered_map<string, int>& Dico , int val ){
string key ;
string empty ;
unordered_map<string, int>::const_iterator it;
for (it = Dico.begin(); it != Dico.end(); ++it){
if (it->second == val){
key = it->first;
return key;
}else {return empty;}
}
}
string findkey2(unordered_map<string, Encoding>& Dico , Encoding val ){
string key ;
string empty ;
unordered_map<string, Encoding>::const_iterator it;
for (it = Dico.begin(); it != Dico.end(); ++it){
if (it->second == val){
key = it->first;
return key;
}else {return empty;}
}
}
void InitDico (unordered_map<string, int>& Dico) {
Dico.clear();
string s = "";
char c;
for (code = 0; code < 256; code++)
{
c = (char)code;
s += c;
Dico[s] = code;
s.clear();
}
}
void InitDico2 (unordered_map<string, Encoding>& Dico) {
Dico.clear();
string s = "";
char c;
for (code = 0; code < 256; code++)
{
c = (char)code;
s+= c;
Encoding sizeplus = Dico.size();
Dico[s] = sizeplus;
s.clear();
}
}
void compress(ifstream &is, ofstream &of){
unordered_map<string,int> Dico ;
InitDico(Dico);
string s = "";
char c ;
while(is.get(c)){
if(Dico.size() == MAX){
InitDico(Dico);
}
if(Dico.count(combi(s,c))){
s += c;
}else{
Dico.insert({(combi(s,c)),code});
code ++;
of.write(reinterpret_cast<const char *> (&Dico.at(s)),sizeof(code));
s = c;
}
}
of.write(reinterpret_cast<const char *> (&Dico.at(s)),sizeof(code));
}
void compress2(ifstream &is, ofstream &of){
unordered_map<string,Encoding> Dico ;
InitDico2(Dico);
string s = "";
char c ;
int max = numeric_limits<Encoding>::max();
while(is.get(c)){
if(Dico.size() == max){
InitDico2(Dico);
}
if(Dico.count(combi(s,c))){
s += c;
}else{
Encoding sizeplus = Dico.size();
Dico[{(combi(s,c))}] = sizeplus;
of.write(reinterpret_cast<const char *> (&Dico.at(s)),sizeof(Encoding));
s = c;
}
}
of.write(reinterpret_cast<const char *> (&Dico.at(s)),sizeof(Encoding));
}
void decompress(ifstream &is, ofstream &of){
unordered_map<string,int> Dico ;
InitDico(Dico);
string s , prevstring;
char c ;
int prevcode,currcode ;
is.read(reinterpret_cast<char *>(&prevcode),sizeof(prevcode));
s = findkey(Dico,prevcode);
of.write(reinterpret_cast<const char *> (&s) , sizeof(s));
while(is.read(reinterpret_cast<char *>(&currcode),sizeof(currcode))){
s = findkey(Dico,currcode);
of.write(reinterpret_cast<const char *> (&s) , sizeof(s));
c =s[0];
prevstring = findkey(Dico,prevcode);
Dico.insert({(combi(prevstring,c)),code});
prevcode = currcode;
}
}
void decompress2(ifstream &is, ofstream &of){//Decompression using uint16 and another algorithm
unordered_map<string,Encoding> Dico ;
InitDico2(Dico);
Encoding n ;
is.read(reinterpret_cast<char*>(&n),sizeof(n));
string v = findkey2(Dico,n);
string w ;
string entry;
of.write(reinterpret_cast<const char *> (&v) , sizeof(v));
w = v ;
while(is.read(reinterpret_cast<char *>(&n),sizeof(n))){
v = findkey2(Dico,n);
if (Dico.count(v)){
entry = v ;
}else{entry = combi(w,w[0]);}
of.write(reinterpret_cast<const char *> (&entry) , sizeof(entry));
Encoding sizeplus = Dico.size();
Dico[combi(w,entry[0])]=sizeplus;
w = entry;
}
}
我看到的一个问题是,当您将解压缩的数据写入文件时,您写入的是字符串 object,而不是字符串 data包含在对象中。为此,您需要获取对象保存的数据。在 decompress
中,将您的两个写入替换为
of.write(s.c_str(), s.length());
需要在 decompress2
中进行类似更改(两次)。
我正在尝试对 lzw 数据进行编码 compressor/decompressor,br/>
所以我确实使用 this Algorithm 制作了一个压缩器(它似乎可以工作但也许不工作)但是当我尝试解压缩它时,我得到一个奇怪的结果,看起来完全不像原始文件...
我认为我的错误在于我从文件中获取 and/or 使用数据的方式,但我不确定......所以这是我用来压缩和解压缩的功能,当然欢迎任何评论/问题。
编辑:给一个 MCVE
正在压缩的输入文本文件包含:banana_bandana
解压输出结果:ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ# ü# ìû# ÿ #ü#ìû#ÿ#ü#ìû#ÿ#ü#
编辑 2:重现输出的所有有用功能:
using Encoding = uint16_t;
#define MAX 4096 //2^12
static int code = 0;
string combi (string s , char c ){
s += c ;
return s;
}
string findkey(unordered_map<string, int>& Dico , int val ){
string key ;
string empty ;
unordered_map<string, int>::const_iterator it;
for (it = Dico.begin(); it != Dico.end(); ++it){
if (it->second == val){
key = it->first;
return key;
}else {return empty;}
}
}
string findkey2(unordered_map<string, Encoding>& Dico , Encoding val ){
string key ;
string empty ;
unordered_map<string, Encoding>::const_iterator it;
for (it = Dico.begin(); it != Dico.end(); ++it){
if (it->second == val){
key = it->first;
return key;
}else {return empty;}
}
}
void InitDico (unordered_map<string, int>& Dico) {
Dico.clear();
string s = "";
char c;
for (code = 0; code < 256; code++)
{
c = (char)code;
s += c;
Dico[s] = code;
s.clear();
}
}
void InitDico2 (unordered_map<string, Encoding>& Dico) {
Dico.clear();
string s = "";
char c;
for (code = 0; code < 256; code++)
{
c = (char)code;
s+= c;
Encoding sizeplus = Dico.size();
Dico[s] = sizeplus;
s.clear();
}
}
void compress(ifstream &is, ofstream &of){
unordered_map<string,int> Dico ;
InitDico(Dico);
string s = "";
char c ;
while(is.get(c)){
if(Dico.size() == MAX){
InitDico(Dico);
}
if(Dico.count(combi(s,c))){
s += c;
}else{
Dico.insert({(combi(s,c)),code});
code ++;
of.write(reinterpret_cast<const char *> (&Dico.at(s)),sizeof(code));
s = c;
}
}
of.write(reinterpret_cast<const char *> (&Dico.at(s)),sizeof(code));
}
void compress2(ifstream &is, ofstream &of){
unordered_map<string,Encoding> Dico ;
InitDico2(Dico);
string s = "";
char c ;
int max = numeric_limits<Encoding>::max();
while(is.get(c)){
if(Dico.size() == max){
InitDico2(Dico);
}
if(Dico.count(combi(s,c))){
s += c;
}else{
Encoding sizeplus = Dico.size();
Dico[{(combi(s,c))}] = sizeplus;
of.write(reinterpret_cast<const char *> (&Dico.at(s)),sizeof(Encoding));
s = c;
}
}
of.write(reinterpret_cast<const char *> (&Dico.at(s)),sizeof(Encoding));
}
void decompress(ifstream &is, ofstream &of){
unordered_map<string,int> Dico ;
InitDico(Dico);
string s , prevstring;
char c ;
int prevcode,currcode ;
is.read(reinterpret_cast<char *>(&prevcode),sizeof(prevcode));
s = findkey(Dico,prevcode);
of.write(reinterpret_cast<const char *> (&s) , sizeof(s));
while(is.read(reinterpret_cast<char *>(&currcode),sizeof(currcode))){
s = findkey(Dico,currcode);
of.write(reinterpret_cast<const char *> (&s) , sizeof(s));
c =s[0];
prevstring = findkey(Dico,prevcode);
Dico.insert({(combi(prevstring,c)),code});
prevcode = currcode;
}
}
void decompress2(ifstream &is, ofstream &of){//Decompression using uint16 and another algorithm
unordered_map<string,Encoding> Dico ;
InitDico2(Dico);
Encoding n ;
is.read(reinterpret_cast<char*>(&n),sizeof(n));
string v = findkey2(Dico,n);
string w ;
string entry;
of.write(reinterpret_cast<const char *> (&v) , sizeof(v));
w = v ;
while(is.read(reinterpret_cast<char *>(&n),sizeof(n))){
v = findkey2(Dico,n);
if (Dico.count(v)){
entry = v ;
}else{entry = combi(w,w[0]);}
of.write(reinterpret_cast<const char *> (&entry) , sizeof(entry));
Encoding sizeplus = Dico.size();
Dico[combi(w,entry[0])]=sizeplus;
w = entry;
}
}
我看到的一个问题是,当您将解压缩的数据写入文件时,您写入的是字符串 object,而不是字符串 data包含在对象中。为此,您需要获取对象保存的数据。在 decompress
中,将您的两个写入替换为
of.write(s.c_str(), s.length());
需要在 decompress2
中进行类似更改(两次)。