zoukankan      html  css  js  c++  java
  • 文件压缩day4——针对单个文件压缩和解压全体解决。

      上次说到还留有两个问题。

      这次我们先处理第一问:

      为什么解压到一半就停止的情况,问题在于我们解压部分的函数的循环判断。

      我们知道,我们用哈夫曼码形成字符压入压缩文件,但是,哈夫曼码极有可能会组成11111111也就是-1,即很有可能达成循环终止条件造成退出,所以我们需要适当修改一下代码——

      

     1     while (count > 0)
     2     {
     3         _c = f_in.get();
     4         for (size_t i = 0; i < 8; i++)
     5         {
     6             if ((_c & 1) == 0)//'1'
     7                 cur = cur->_left;
     8             else                 //'0'
     9                 cur = cur->_right;
    10             //叶子
    11             if (cur->_left == NULL && cur->_right == NULL)
    12             {
    13                 f_out.put(cur->_val._ch);
    14                 cur = MyHuffman.GetRoot();
    15                 --count;
    16                 if (count <= 0)
    17                     break;
    18             }
    19             _c >>= 1;
    20         }
    21     }    

      我们要注意的是,不能写成count != 0 (当然如果在代码中加了一个break的话,那就问题不大了),因为很有可能解完了,因为后续还有0,没有退出for的那层循环,接着解导致死循环(程序崩溃)。

      我们现在来探讨第二个问题:要将压缩和解压缩功能分开,为何解压缩不成功?

      其实很好理解,你在解压缩时,你的类对象重新构造,哈希表里什么都没有,自然不可能解压缩成功啦,所以我们要做的,就是在压缩时将哈希表也压缩进来,而解压缩时,先提取哈希表,然后再解压缩,看如下代码——

      

     1 //要将哈希表的重要内容都写到解压文件中
     2     //千万注意一定要置零,因为最初的情况下!!!都是随机数
     3     //解压时需要以0为判断!!!
     4 
     5     //只要遇到一个在哈希表中存在个数的,就可以放进压缩文件中!!!
     6     ImpoInfo buf;
     7     memset(&buf, 0x00, sizeof(ImpoInfo));
     8 
     9     for (size_t i = 0; i < 256; ++i)
    10     {
    11         if (_hashInfos[i]._count != 0)
    12         {
    13             buf._ch = _hashInfos[i]._ch;
    14             buf._count = _hashInfos[i]._count;
    15 
    16             f_out.write(reinterpret_cast<char*>(&buf), sizeof(ImpoInfo));
    17             memset(&buf, 0x00, sizeof(ImpoInfo));
    18         }
    19     }
    20     //最后以一个放了-1的表示终止!!!
    21     buf._count = -1;
    22 
    23     f_out.write(reinterpret_cast<char*>(&buf), sizeof(ImpoInfo));
     1 //读哈希表重要信息
     2     ImpoInfo buf;
     3     memset(&buf, 0x00, sizeof(ImpoInfo));//可置可不置
     4 
     5     f_in.read(reinterpret_cast<char*>(&buf), sizeof(ImpoInfo));
     6 
     7     while (buf._count != -1)
     8     {
     9         _hashInfos[static_cast<unsigned char>(buf._ch)]._count = buf._count;
    10         memset(&buf, 0x00, sizeof(ImpoInfo));
    11         
    12         f_in.read(reinterpret_cast<char*>(&buf), sizeof(ImpoInfo));
    13     }

      需要特别注意,拷贝哈希表时是用二进制写入和二进制读出的,因为二进制是完完全全的拷贝过去,虽然用户不可视,但是信息保存的比较好。

      ps:vs2013在创建文件时,要用上构造函数的第二个参数,并且加上std::ios::out | std::ios::binary 或std::ios::in | std::ios::binary。

       vs2008可以忽略。

  • 相关阅读:
    C# 解析js方法,并调用js方法
    Net 面试题_代码
    最近小项目总结 2013.5.3
    程序集生成失败 引用的程序集“Interop.MSScriptControl”没有强名称
    Vs 使用 (快捷等)
    Ildasm.exe 反汇编程序使用
    MSSQL_1
    [异常] Asp.net 中异常处理
    Net 面试题_理论(总结网上流传的)
    反射
  • 原文地址:https://www.cnblogs.com/shy0322/p/9245178.html
Copyright © 2011-2022 走看看