Advertisement
Guest User

Untitled

a guest
Dec 18th, 2017
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.31 KB | None | 0 0
  1. #include <fcntl.h> //нужна для открытия и закрытия файла
  2. #include <string.h>
  3. #include <sys/stat.h> //хранит ключи открытия и закрытия файла
  4.  
  5. class BFILE // Класс для ввода-вывода
  6. {
  7.     int handle; // хранится открытый файл
  8.     unsigned char buffer, mask; // буфер, маска
  9. public:
  10.     void aread(int h); // связывание для чтения
  11.     void awrite(int h); // связывание для записи
  12.     void SetZero(); // заполнение нулями
  13.  
  14.     void putbit(bool val); // запись бита
  15.     bool getbit(); //чтение бита
  16.  
  17.     void putbits(int val, int n); // запись n битов
  18.     int getbits(int n); // чтение n битов
  19. };
  20.  
  21. // заполнение нулями
  22. void BFILE::SetZero()
  23. {
  24.     for (int i = 0; i < 7; i++) putbit(0);
  25. }
  26.  
  27. // связывание для записи
  28. void BFILE::awrite(int h)
  29. {
  30.     handle = h;
  31.     buffer = 0;
  32.     mask = 128;
  33. }
  34.  
  35. // связывание для чтения
  36. void BFILE::aread(int h)
  37. {
  38.     handle = h;
  39.     buffer = 0;
  40.     mask = 0;
  41. }
  42.  
  43. //чтенние бита
  44. bool BFILE::getbit()
  45. {
  46.     if ((mask >>= 1) == 0) //побитовый сдвиг 1 вправо
  47.     {
  48.         read(handle, &buffer, 1); //считываем из файла один символ из буфера
  49.         mask = 128;//двоичное 10000000
  50.     }
  51.     return (buffer & mask) != 0;
  52. }
  53.  
  54. // запись бита
  55. void BFILE::putbit(bool val)
  56. {
  57.     if (val) buffer |= mask;
  58.     if ((mask >>= 1) == 0) //побитовый сдвиг 1 вправо
  59.     {
  60.         write(handle, &buffer, 1); // записываем в файл один символ из буфера
  61.         buffer = 0;
  62.         mask = 128;//двоичное 10000000
  63.     }
  64. }
  65.  
  66. // запись n битов
  67. void BFILE::putbits(int val, int n)
  68. {
  69.     int m = 1;
  70.     for (int i = 0; i < n; i++)
  71.     {
  72.         putbit((val & m) != 0);
  73.         m <<= 1; //побитовый сдвиг 1 влево
  74.     }
  75. }
  76.  
  77. // чтение n битов
  78. int BFILE::getbits(int n)
  79. {
  80.     int result = 0;
  81.     for (int i = 0; i < n; i++)
  82.         result |= getbit() << i;
  83.     return result;
  84. }
  85.  
  86. #define BUF_LEN 15 //максимальная длина буфера
  87. #define DICT_LEN 256 //максимальная длина словаря
  88.  
  89. int input;  // входной файл
  90. int output; // выходной файл
  91. BFILE pfile;
  92.  
  93. /*
  94.  Сделаем буфер на 1 больше, т. к. в find_match
  95.  `unmatched = buffer[match_len];` а match_len
  96.  может достигать BUF_LEN
  97. */
  98. char buffer[BUF_LEN + 1], dict[DICT_LEN]; //буфер, словарь
  99. int match_pos, match_len, unmatched; // позиция совпадения, длина совпадения, несовпавшее
  100. int dict_pos = 0; //позиция в словаре
  101.  
  102. /*
  103.  Возвращает позицию sub от КОНЦА src. от 1 до len
  104.  Если не найдено возвращает 0
  105. */
  106. int strpos(char *src, int len, char *sub, int sub_len)
  107. {
  108.     for (int i = 0; i <= (len - sub_len); i++)
  109.         if (memcmp(src + i, sub, sub_len) == 0) return len - i; //сравнение данных в src и sub
  110.     return 0;
  111. }
  112.  
  113. // добавление в словарь символа
  114. void add_dict(char c)
  115. {
  116.     if (dict_pos == (DICT_LEN - 1)) //если дошли до конца словаря
  117.     {
  118.         memcpy(dict, dict + 1, DICT_LEN - 1); //копируем данные
  119.         dict[dict_pos - 1] = c; //добавляем символ в конец словаря
  120.     }
  121.     else
  122.     {
  123.         dict[dict_pos] = c; //добавляем символ в словарь
  124.         dict_pos++;
  125.     }
  126. }
  127.  
  128. // поиск совпадения в словаре
  129. void find_match()
  130. {
  131.     match_len = 0;
  132.     match_pos = 1;
  133.     while(match_len < BUF_LEN) //пока длина совпадения меньше длины буфера
  134.     {
  135.         read(input, &buffer[match_len], 1); //считываем один символ из файла
  136.         if (eof(input)) break; //если дошли до конца файла, то выйти
  137.         int pos1 = strpos(dict, dict_pos, buffer, match_len + 1);
  138.         if (pos1 == 0) break;
  139.         match_pos = pos1;
  140.         match_len++;
  141.     }
  142.     unmatched = buffer[match_len];
  143. }
  144.  
  145. // компрессия
  146. void encode()
  147. {
  148.     while(!eof(input)) //пока не дойдем до конца файла
  149.     {
  150.         find_match(); // поиск совпадения в словаре
  151.         pfile.putbits(match_pos, 8); //заполняем 8 бит
  152.         pfile.putbits(match_len, 4); //заполняем 4 бита
  153.         if (match_len < BUF_LEN) // если длина совпадения меньше длины буфера
  154.             pfile.putbits(unmatched, 8);
  155.  
  156.         for (int i = 0; i < match_len; i++)
  157.             add_dict(buffer[i]); //добавление в словарь буфера
  158.         if (match_len < BUF_LEN) // если длина совпадения меньше длины буфера
  159.             add_dict(unmatched); //добавление в словарь несовпавшего
  160.     }
  161.     pfile.putbits(0, 8);
  162.     pfile.SetZero(); //заполняем нулями
  163. }
  164.  
  165. // декомпрессия
  166. void decode()
  167. {
  168.     char c;
  169.     int i;
  170.     for(;;)
  171.     {
  172.         match_pos = pfile.getbits(8); //получаем 8 бит
  173.         if (match_pos == 0) break; //если нет совпадений, то переходим к следующей итерации
  174.         match_len = pfile.getbits(4); //получаем 4 бита
  175.         memcpy(buffer, dict + dict_pos - match_pos, match_len); //копируем данные
  176.         write(output, buffer, match_len); //записываем раскодированные данные
  177.         for (i = 0; i < match_len; i++)
  178.             add_dict(buffer[i]); //добавление в словарь
  179.         if (match_len < BUF_LEN) // если длина совпадения меньше длины буфера
  180.         {
  181.             c = pfile.getbits(8);
  182.             add_dict(c); //добавление символа в словарь
  183.             write(output, &c, 1); //записываем раскодированный символ
  184.         }
  185.     }
  186. }
  187.  
  188. int main()
  189. {
  190. // открытие входного и выходного файлов
  191.     input = open("in.txt", _O_BINARY | _O_RDWR, _S_IREAD | _S_IWRITE); //ключи открытия файла
  192.     output = open("out.txt", _O_BINARY | _O_WRONLY | _O_CREAT | _O_TRUNC, _S_IREAD | _S_IWRITE); //ключи открытия файла
  193.  
  194.     pfile.awrite(output); // связывание файла (assign)
  195.     encode(); // кодирование
  196.  
  197.     close(input);
  198.     close(output);
  199.  
  200.     // открытие входного и выходного файлов
  201.     input = open("out.txt", _O_BINARY | _O_RDWR, _S_IREAD | _S_IWRITE); //ключи открытия файла
  202.     output = open("data.txt", _O_BINARY | _O_WRONLY | _O_CREAT | _O_TRUNC, _S_IREAD | _S_IWRITE); //ключи открытия файла
  203.  
  204.     pfile.aread(input); // связывание файла (assign)
  205.     decode(); // кодирование
  206.  
  207.     close(input);
  208.     close(output);
  209.  
  210.     return 0;
  211. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement