LZW减压c ++

时间:2018-06-22 00:58:16

标签: c++ lzw

我正在尝试对lzw数据压缩器/解压缩器进行编码,br />
所以我确实使用this Algorithm制作了一个压缩器(似乎可以正常工作,但可能无法工作),但是当我尝试进行解压缩时我得到一个奇怪的结果,根本不像原始文件一样...

我认为我的错误在于我从文件中获取和/或使用数据的方式,但是我不确定……所以这里是我用来压缩和解压缩的函数,当然,欢迎任何批评家/问题。

编辑:给出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;
    }

}

1 个答案:

答案 0 :(得分:1)

我看到的一个问题是,当您将解压缩的数据写到文件中时,您写的是字符串 object ,而不是对象中包含的字符串 data 。为此,您需要获取对象保存的数据。在decompress中,将您所有的写入都替换为

of.write(s.c_str(), s.length());

decompress2中需要进行类似的更改(两次)。