聊聊字符集编码与数据压缩( 二 )


文章插图
 
字符集转换编程:
#include <iconv.h>
函数:iconv_t iconv_open (const char* tocode, const char* fromcode);
范例:iconv_t cd = iconv_open(“UTF−8”, “UTF−16”);
函数:int iconv_close (iconv_t cd);
范例:iconv_close(cd);
函数:size_t iconv (iconv_t cd, const char* * inbuf, size_t * inbytesleft, char* * outbuf,
size_t * outbytesleft);
返回值:返回-1 则说明出现异常 , 错误码
E2BIG:outbuf 没有足够的空间
EILSEQ:遇到无效的多字节序列
EINVAL:遇到不完整的多字节序列
字符集在线工具集合
GBK 内码查询:
http://www.mytju.com/classcode/tools/encode_gb2312.a
完整的 Unicode 字符集:
https://unicode-table.com/c
Unicode 和 UTF 编码转换:
https://www.qqxiuzi.cn/bianma/Unicode-UTF.p
汉字字符集编码查询:
https://www.qqxiuzi.cn/bianma/zifuji.p
3.压缩原理
压缩原理就是找到重复出现的字符串 , 然后用更短的符号代替 , 从而达到缩短字符串的目的 。本质上 , 所谓就是找出文件内容的概率分布 , 将出现概率高的部分代替为更短的形式 。内容越重复的文件 , 可以压缩的越小 。如 , "ABABABABABABAB"可以压缩成"7AB" 。反之内容毫无重复 , 就很难压缩 , 极端情况就是 , 均匀分布的随机字符串 , 往往一个字符都无法压缩 , 如任意排列的10个阿拉伯数组(123456789) , 就无法压缩 , 再如π , 也很难 。
香农极限
∑ log2(1/pn) / n = log2(1/p1)/n + log2(1/p2)/n + ... + log2(1/pn)/n;
(1)如果两个文件都包含了1024个符号 , 在ASCII 码情况下 , 长度是相等 , A文件(只包含abc)的内容50%是 a , 30%b , 20%是 c , 则平均每个符号要占用1.49个二进制位 。
0.5*log2(1/0.5) + 0.3*log2(1/0.3) + 0.2*log2(1/0.2) = 1.49
(2)假如B文件的每个字节出现的概率是0-255 , 均匀分布的出现概率是1/256 , 则 pn = 1/256 , 计算出极限为 8 。
Log21/(1/256) = Log2256 = 8
4.Deflate 压缩算法
deflate是一种压缩数据流的算法 , 任何需要流式压缩的地方都可以 , deflate是zip压缩文件的默认算法 , 除了zip文件 , 还有7z , xz等其他压缩文件 , 也是用 。
deflate 算法下的压缩器有三种压缩模型:
(1)不压缩数据 , 对于已经压缩的数据 , 不再压缩 , 这样的数据会稍微增加 , 但会小于其它应用的一种压缩算法 。
(2)先用L7zz , 再用huffman 编码 。压缩的树是Deflate规范定义 , 所以不需要额外的空间来存储这个树 。
(3)先用LZ77 , 然后再用huffman 编码 。压缩树由压缩器生成 , 并与数据一起存储 。
如果数据被分割成不同块 , 必须使用单一的压缩模式 , 如果要在这三种压缩模式中相互切换 , 必须先结束当前块 , 重新开始一个新的块 。
5.LZ77 算法原理
采用字典的方式进行压缩 , 是一个简单高效的数据压缩算法 。把数据中的一些可以组织成短语的字符加入字典 , 然后再有相同字符出现采用毕节来代替字典中的短语 , 如此通过标记代替多数重复出现的方式以进行压缩 。需先了解 3 个关键词:短语字典 , 滑动窗口和向前缓冲区 。
(1)前向缓冲区
每次读取数据的时候 , 先把一部分数据预载入前向缓冲区 。为移入滑动窗口做准备
(2)一旦数据通过缓冲区 , 那么它将移动到滑动窗口中 , 并变成字典的一部分 。滑动窗口需要预设一个定值 。
(3) 比如字符(A,B,D) ,可以组合的短语为{(A),(A,B),(A,B,D),(B),(B,D),(D)},如果这些字符在滑动窗口里面 , 可以标记为当前的短语字典 , 滑动窗口不断向前滑动 , 短语字典也不断变化 。
注意:先通过前向缓冲区预读数据 , 然后再向滑动窗口移入(滑动窗口有一定长度) , 在这个过程中 , 不断寻找与字典中短语匹配的最长短语 , 最终通过标记符标记 , 以ABD为例子 。这里滑动窗口 和前向缓冲区可以匹配的最长短语是(A,B) , 然后向前移动的时候再次遇到(A,B)的时候采用标记符代替 。


推荐阅读