Guest User

Untitled

a guest
Jul 20th, 2018
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.17 KB | None | 0 0
  1. #include <vector>
  2. #include <iostream>
  3. #include <fstream>
  4. using namespace std;
  5. struct recordLZW{
  6.     unsigned short index;
  7.     unsigned short prev_index;
  8.     recordLZW(unsigned short index,unsigned short prev_index){
  9.         this->index = index;
  10.         this->prev_index = prev_index;
  11.     }
  12.     bool operator==(const recordLZW& r){
  13.         return (index==r.index)&&(prev_index==r.prev_index);
  14.     }
  15. };
  16. class LZW{
  17. private:
  18.     const char* txtfilename;
  19.     const char* lzfilename;
  20.     ifstream infile;
  21.     ofstream outfile;
  22.     vector<recordLZW> dictionary;
  23.     int inDictionary(const recordLZW& r){
  24.         for(unsigned int i = 0;i<dictionary.size();++i) if(dictionary[i] == r) return i;
  25.         return -1;
  26.     }
  27. public:
  28.     LZW(const char* txtfilename, const char* lzfilename){
  29.         this->txtfilename = txtfilename;
  30.         this->lzfilename = lzfilename;
  31.         for(unsigned short i=0;i<256;++i) {
  32.             recordLZW tmp(i,0);
  33.             dictionary.push_back(tmp);
  34.         }
  35.     }
  36.     void drawDictionary(){
  37.         for(unsigned int i=256;i<dictionary.size();++i) cout<<i<<":"<<dictionary[i].prev_index<<"("<<(char)dictionary[i].prev_index<<")  "<<dictionary[i].index<<"("<<(char)dictionary[i].index<<")"<<endl;
  38.     }
  39.     char firstChar(unsigned short code){
  40.         if(!dictionary[code].prev_index)
  41.             return (char)dictionary[code].index;
  42.         do{
  43.             if(dictionary[code].prev_index<255) return (char)dictionary[code].prev_index;
  44.             else code = dictionary[code].prev_index;
  45.         }while(true);
  46.     }
  47.     void decompress(){
  48.         infile.open(lzfilename,ifstream::binary);
  49.         outfile.open(txtfilename,ofstream::binary);
  50.         unsigned short current_code;
  51.         unsigned short previous_code = 0;
  52.         char* buffer = new char[65535];
  53.         infile.read((char*)&previous_code,sizeof(unsigned short));
  54.         outfile.put((char)previous_code);
  55.         while(true){
  56.             int bufsize = 0;
  57.             if(infile.good()){
  58.                 infile.read((char*)&current_code,sizeof(unsigned short));
  59.                 if(infile.eof()) break;
  60.                 if(dictionary.size()>current_code){ //ячейка dictionary[current_code] заполнена
  61.                     //выводим table[current_code]
  62.                     int picode = current_code;
  63.                     do{
  64.                         buffer[bufsize++] = (char)dictionary[picode].index;
  65.                         if(dictionary[picode].prev_index<256) {
  66.                             if(dictionary[picode].prev_index>0)
  67.                                 buffer[bufsize++]=(char)dictionary[picode].prev_index;
  68.                             break;
  69.                         }
  70.                         else picode = dictionary[picode].prev_index;
  71.                     }while(true);
  72.                     for(int i=bufsize-1;i>=0;--i){
  73.                         outfile.put(buffer[i]);
  74.                     }
  75.                     //выволы
  76.                     recordLZW tmp((unsigned short)firstChar(current_code), previous_code);
  77.                     dictionary.push_back(tmp);
  78.                     previous_code = current_code;
  79.                 }else{//если ячейки не существу
  80.                     recordLZW tmp((unsigned short)firstChar(previous_code),previous_code);
  81.                     dictionary.push_back(tmp);
  82.                     int picode = dictionary.size() - 1;
  83.                     do{
  84.                         buffer[bufsize++] = (char)dictionary[picode].index;
  85.                         if(dictionary[picode].prev_index<256) {
  86.                             if(dictionary[picode].prev_index>0)
  87.                                 buffer[bufsize++]=(char)dictionary[picode].prev_index;
  88.                             break;
  89.                         }
  90.                         else picode = dictionary[picode].prev_index;
  91.                     }while(true);
  92.                     for(int i=bufsize-1;i>=0;--i){
  93.                         outfile.put(buffer[i]);
  94.                     }
  95.                 }
  96.             }else{
  97.                 break;
  98.             }
  99.         }
  100.         delete[] buffer;
  101.         //drawDictionary();
  102.         infile.close();
  103.         outfile.close();
  104.     }
  105.     void STUPIDdecompress(){
  106.         infile.open(lzfilename,ifstream::binary);
  107.         outfile.open(txtfilename,ofstream::binary);
  108.         unsigned short current_code;
  109.         char* buffer = new char[65535];
  110.         unsigned short old_code = 0;
  111.         while(true){
  112.             infile.read((char*)&current_code, sizeof(unsigned short));
  113.             int bufsize = 0;
  114.             if(infile.good()){
  115.                 if(current_code<256){
  116.                     recordLZW tmp(current_code,old_code);
  117.                     cout<<current_code;
  118.                     outfile.put((char)current_code);
  119.                     if(old_code){
  120.                         dictionary.push_back(tmp);
  121.                         cout<<" Добавляем 1 "<<dictionary.size()-1<<"  "<<dictionary[dictionary.size() - 1].prev_index<<","<<dictionary[dictionary.size() - 1].index<<endl;
  122.                     }
  123.                 }else{
  124.                     cout<<"Нужен "<<current_code<<" имеется "<<dictionary.size()-1<<endl;
  125.                     if(dictionary.size()>current_code){
  126.                         //outfile.put((char)dictionary[current_code].prev_index);
  127.                         //outfile.put((char)dictionary[current_code].index);
  128.                         int picode = current_code;
  129.                         cout<<"Record: "<<current_code<<" - "<<dictionary[current_code].prev_index<<","<<dictionary[current_code].index<<endl;
  130.                         bufsize=0;
  131.                         do{
  132.                             buffer[bufsize++] = (char)dictionary[picode].index;
  133.                             if(dictionary[picode].prev_index<256) {
  134.                                 buffer[bufsize++]=(char)dictionary[picode].prev_index;
  135.                                 break;
  136.                             }
  137.                             else picode = dictionary[picode].prev_index;
  138.                         }while(true);
  139.                         for(int i=bufsize-1;i>=0;--i){
  140.                             outfile.put(buffer[i]);
  141.                         }
  142.                     }else{
  143.                         //oldcode first char
  144.                         char fch = firstChar(old_code);
  145.                         //cout<<"FC "<<fch<<endl;
  146.                         recordLZW tmp(fch,old_code);
  147.                         dictionary.push_back(tmp);
  148.                         cout<<"Добавляем 2 "<<dictionary.size()-1<<"   "<<dictionary[dictionary.size() - 1].prev_index<<","<<dictionary[dictionary.size() - 1].index<<endl;
  149.                         if(old_code>255) { // Дописать алгоритм распаковки буфера на лету
  150.                             int picode = old_code;
  151.                             bufsize=0;
  152.                             do{
  153.                                 buffer[bufsize++] = (char)dictionary[picode].index;
  154.                                 if(dictionary[picode].prev_index<256) {
  155.                                     buffer[bufsize++]=(char)dictionary[picode].prev_index;
  156.                                     break;
  157.                                 }
  158.                                 else picode = dictionary[picode].prev_index;
  159.                             }while(true);
  160.                             for(int i=bufsize-1;i>=0;--i){
  161.                                 outfile.put(buffer[i]);
  162.                             }
  163.                         }else{
  164.                             outfile.put((char)old_code);
  165.                         }
  166.                         outfile.put(fch);
  167.                     }
  168.                     //continue;//FIX IT
  169.                 }
  170.                 old_code = current_code;
  171.             }else break;
  172.         }
  173.         delete[] buffer;
  174.         drawDictionary();
  175.         infile.close();
  176.         outfile.close();
  177.     }
  178.     void compress(){
  179.         infile.open(txtfilename,ifstream::binary);
  180.         outfile.open(lzfilename,ofstream::binary);
  181.         unsigned char buffer;
  182.         unsigned short prefix = 0;
  183.         while(true){
  184.             infile.read((char*)&buffer,1);
  185.             if(infile.good()) {
  186.                 recordLZW tmp(static_cast<unsigned short>(buffer),prefix);
  187.                 int find_index = inDictionary(tmp);
  188.                 cout<<"Структура :"<<tmp.prev_index<<"("<<(char)tmp.prev_index<<")  "<<tmp.index<<"("<<(char)tmp.index<<")";
  189.                 if(find_index>=0) {
  190.                     cout<<"        [найдена]"<<endl;
  191.                     prefix = (unsigned short)find_index;
  192.                     //if(prefix>255){
  193.                         //outfile.write((char*)&prefix,sizeof(prefix));
  194.                         //prefix = buffer;
  195.                         //cout<<prefix<<" "<<sizeof(prefix)<<endl;
  196.                     //}
  197.                 }
  198.                 else{
  199.                     dictionary.push_back(tmp);
  200.                     //if(prefix<=255) //FIX IT исправлено для абракадабры, для других может не работать. лишний 00 01
  201.                         outfile.write((char*)&prefix,sizeof(unsigned short));
  202.                     //cout<<prefix<<endl;
  203.                     cout<<"        [добавлена]"<<endl;
  204.                     prefix = buffer;
  205.                 }
  206.             }else{
  207.                 if(prefix) outfile.write((char*)&prefix,sizeof(unsigned short));
  208.                 break;
  209.             }
  210.         }
  211.         cout<<endl<<dictionary.size() - 256;
  212.         cout<<endl;
  213.         infile.close();
  214.         outfile.close();
  215.         drawDictionary();
  216.     }
  217. };
Add Comment
Please, Sign In to add comment