敞开成长之旅!这是我参加「日新方案 2 月更文挑战」的第 15 天,点击检查活动概况

1. 前言

在开发中咱们难免会碰到传输的数据太大,或许传输的资源过大,所以就呈现了数据紧缩这项技术,现在存在许多种数据紧缩的算法,每种算法都有自己的特色和运用场景,这次就想简略来聊聊关于数据紧缩这件事。

为什么会想到这个问题,由于碰到了一些场景,我不知道是大家对数据紧缩这个概念太含糊不敢去运用,仍是由于深思熟虑觉得影响功能太大不想用。我这有个需求,给链接拼接参数,然后跳转这个链接,别的一边从中拿到拼接的参数,其实便是get请求,但是,现在的情况是拼接后的链接又臭又长,便是url?a=xxx&b=xxx&c=xxx……这种,然后就疯狂往后边拼参数。把整个目标拆了往后边拼。那为何不把目标转成json然后紧缩呢?

是觉得字符串不能紧缩?仍是设计时没有意识到还有紧缩这事?仍是觉得你几十年的开发直觉告知你运用紧缩会出大问题。

2. 关于紧缩这件事

首先什么是数据紧缩?举个简略的比方,我把AAABBBCCC这个字符串变成3A3B3C,便是一种紧缩的思维。

写个Demo演示一下java运用Deflater对字符串进行紧缩

public class Test {
    public static String compress(String str) {
        Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
        deflater.setInput(str.getBytes());
        deflater.finish();
        final byte[] bytes = new byte[256];
        ByteArrayOutputStream bos = new ByteArrayOutputStream(256);
        while (!deflater.finished()) {
            int length = deflater.deflate(bytes);
            bos.write(bytes, 0, length);
        }
        deflater.end();
        String result = Base64.encodeToString(bos.toByteArray(), Base64.NO_PADDING);
        Log.v("mmp", "紧缩后成果" + result);
        return result;
    }
}

在外部调用

String str = "ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE";
String result = Test.compress(str);

能够看到成果
紧缩后成果eNpzdHJ2cXUkhQAATY4NFw

看得出紧缩前和紧缩后的一个明显的效果。

有人看到这个或许就想到,哦,原来用Base64紧缩,这是一个误区,有必定开发经验或许必定根底的朋友都知道,但是或许一些萌新不太熟,我前面也写过了,Base64不是紧缩,是一种编码,假如你纯用Base64的话,它只会变得更长。

那为什么还要在这儿用Base64呢?Base64是为了将字节数组转成字符串,数据紧缩和解压的目标是字节数组,所以紧缩能够对字符串紧缩,也能够对文件紧缩,由于它是针对byte[]

有的人就会说,懂了,那简略,那我图片和视频的紧缩也用Deflater。这东西还真不一样,紧缩又分为有损紧缩和无损紧缩,咱们上面运用Deflater进行的紧缩是无损紧缩,是可逆的,而图片和视频的紧缩往往会用有损紧缩比较多,特别是视频,紧缩率很高,由于有损紧缩能把数据压得更小,相对得它是不可逆的。所以对数据和资源要运用哪种紧缩办法要看详细的场景。比方这儿的对字符串紧缩,要是运用有损的办法,那解压出来的字符串不就和原字符串内容不同了吗。

信任看到这儿,你现已对数据的紧缩这个概念有个大约的了解。

3. Deflater算法

前面有提到数据紧缩的算法有许多种,乃至你也能够自己设计出一套算法,然后写专利。而Deflater算法是一种常用的数据无损紧缩算法。

能够很容易的找到Deflate紧缩算法=LZ77+哈夫曼编码,意思是这套算法内部的完成原理便是运用LZ77和哈夫曼编码。

我这边暂时先不讲这些算法的完成进程和原理,由于内容也是比较多,假如以后有时间独自拿出来写,而且手写一遍用代码去完成这些算法(一般都是用C写) ,这儿就只简略介绍一下,有个概念就行。

LZ77

LZ77编码是一种基于字典的、“滑动窗”的无损紧缩算法。

简略来说便是滑动的进程中,把前面的子串放到字典中,滑动到后边发现相同的子串时只需求替换成子串的位置和长度的信息进去就行。

例如ABCDEFABCDZZZ → ABCDEF(6,4)ZZZ
意思是往前第6个,长度为4。

当然这只是简略的一个表现思路的比方,实践中必定没有这么简略,比方子串怎样找啊,滑动怎样滑等等之类的。

哈夫曼编码

哈夫曼编码,又触及到哈夫曼树,贪心算法。该办法完全根据字符呈现概率来结构异字头的均匀长度最短的码字。

由于这个要根据字符呈现的频率构建哈夫曼树,欠好简略易懂的演示出来,这儿就拿一个他人写的Demo来直接演示效果。

原字符串:BCAADDDCCACACAC
转成二进制后:10000100100001101000001010000010100010001000100010001000100001101000011010000010100001101000001010000110100000101000011
编码后:1000111110110110100110110110

能看出紧缩的效果很明显。

小结

Deflater算法是一种常用的数据紧缩算法,其内部是运用LZ77和哈夫曼编码。紧缩算法一般都具有渠道无关性,它是一种核算,一种思维,java运用的是Deflater这个类,php也有对应的库,go也有对应的库。乃至当你知道了它的原理之后,你也能自己把完成进程给写出来,当然这很费事,毕竟触及算法仍是有必定难度。所以一般在开发中你得知道有这么一个东西,它是干嘛的,怎样运用。当然最好仍是能知道它的原理,知道它怎样完成的,这并不是毫无作用,当你去学之后,你必定能收获到一些东西。

能够再扩展一下,像图片的质量紧缩,便是一种有损紧缩的办法,像视频的H264编码,H265编码等,也是一个有损的进程。要心里有个底,对这个数据进行操作,是否需求可逆,是否是针对它的巨细,可逆就用无损紧缩的算法,为了极致的紧缩巨细又无所谓不可逆,那就用有损紧缩的算法。对数据的传输是否要安全,全都无所谓就明文传输最快,对其巨细有要求就紧缩,要求安全就加密。开发就这么简略!

4. GZIP

GZIP也是一种紧缩技术,信任许多人都听说过。咱们的http请求头中能够配置content-encoding为gzip,那么服务端回来的数据便是通过gzip紧缩过之后的数据。那有什么用呢?你文件大,字节数多,传输的速度就慢,我通过gizp紧缩之后,紧缩率高,传输的字节数少许多,那传输的速度就快。

有的人也会说,那你紧缩可解压也是耗时间的啊。说得好,这种我建议你不要信什么原理,直接去实践,去试试运用GZIP紧缩和不运用韩国,谁得速度更快。当然数据量大的情况下去测。你会发现哪怕我通过紧缩和解压,也比你直接传输的速度更快。

GZIP中的完成也包含了Deflater算法。所以能看出来,紧缩算法许多,基本都万变不离其宗,基本都是靠LZ77和哈夫曼,为什么呢?由于他人好用啊,你写不出比它更牛逼的,那不用它的用什么。