Android?數(shù)據(jù)壓縮淺析
1. 前言
在開發(fā)中我們難免會碰到傳輸?shù)臄?shù)據(jù)太大,或者傳輸?shù)馁Y源過大,所以就出現(xiàn)了數(shù)據(jù)壓縮這項(xiàng)技術(shù),現(xiàn)在存在很多種數(shù)據(jù)壓縮的算法,每種算法都有自己的特點(diǎn)和使用場景,這次就想簡單來聊聊關(guān)于數(shù)據(jù)壓縮這件事。
為什么會想到這個(gè)問題,因?yàn)榕龅搅艘恍﹫鼍?,我不知道是大家對?shù)據(jù)壓縮這個(gè)概念太模糊不敢去使用,還是因?yàn)樯钏际鞈]覺得影響性能太大不想用。我這有個(gè)需求,給鏈接拼接參數(shù),然后跳轉(zhuǎn)這個(gè)鏈接,另外一邊從中拿到拼接的參數(shù),其實(shí)就是get請求,但是,現(xiàn)在的情況是拼接后的鏈接又臭又長,就是url?a=xxx&b=xxx&c=xxx......這種,然后就瘋狂往后面拼參數(shù)。把整個(gè)對象拆了往后面拼。那為何不把對象轉(zhuǎn)成json然后壓縮呢?
是覺得字符串不能壓縮?還是設(shè)計(jì)時(shí)沒有意識到還有壓縮這事?還是覺得你幾十年的開發(fā)直覺告訴你使用壓縮會出大問題。
2. 關(guān)于壓縮這件事
首先什么是數(shù)據(jù)壓縮?舉個(gè)簡單的例子,我把AAABBBCCC這個(gè)字符串變成3A3B3C,就是一種壓縮的思想。
寫個(gè)Demo演示一下java使用Deflater對字符串進(jìn)行壓縮
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", "壓縮后結(jié)果" + result);
return result;
}
}
在外部調(diào)用
String str = "ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE"; String result = Test.compress(str);
可以看到結(jié)果
壓縮后結(jié)果eNpzdHJ2cXUkhQAATY4NFw
看得出壓縮前和壓縮后的一個(gè)明顯的效果。
有人看到這個(gè)可能就想到,哦,原來用Base64壓縮,這是一個(gè)誤區(qū),有一定開發(fā)經(jīng)驗(yàn)或者一定基礎(chǔ)的朋友都知道,但是可能一些萌新不太熟,我前面也寫過了,Base64不是壓縮,是一種編碼,如果你純用Base64的話,它只會變得更長。
那為什么還要在這里用Base64呢?Base64是為了將字節(jié)數(shù)組轉(zhuǎn)成字符串,數(shù)據(jù)壓縮和解壓的對象是字節(jié)數(shù)組,所以壓縮可以對字符串壓縮,也可以對文件壓縮,因?yàn)樗轻槍yte[]
有的人就會說,懂了,那簡單,那我圖片和視頻的壓縮也用Deflater。這東西還真不一樣,壓縮又分為有損壓縮和無損壓縮,我們上面使用Deflater進(jìn)行的壓縮是無損壓縮,是可逆的,而圖片和視頻的壓縮往往會用有損壓縮比較多,特別是視頻,壓縮率很高,因?yàn)橛袚p壓縮能把數(shù)據(jù)壓得更小,相對得它是不可逆的。所以對數(shù)據(jù)和資源要使用哪種壓縮方式要看具體的場景。比如這里的對字符串壓縮,要是使用有損的方式,那解壓出來的字符串不就和原字符串內(nèi)容不同了嗎。
相信看到這里,你已經(jīng)對數(shù)據(jù)的壓縮這個(gè)概念有個(gè)大概的了解。
3. Deflater算法
前面有說到數(shù)據(jù)壓縮的算法有很多種,甚至你也可以自己設(shè)計(jì)出一套算法,然后寫專利。而Deflater算法是一種常用的數(shù)據(jù)無損壓縮算法。
可以很容易的找到Deflate壓縮算法=LZ77+哈夫曼編碼,意思是這套算法內(nèi)部的實(shí)現(xiàn)原理就是使用LZ77和哈夫曼編碼。
我這邊暫時(shí)先不講這些算法的實(shí)現(xiàn)過程和原理,因?yàn)閮?nèi)容也是比較多,如果以后有時(shí)間單獨(dú)拿出來寫,并且手寫一遍用代碼去實(shí)現(xiàn)這些算法(一般都是用C寫) ,這里就只簡單介紹一下,有個(gè)概念就行。
LZ77
LZ77編碼是一種基于字典的、“滑動窗”的無損壓縮算法。
簡單來說就是滑動的過程中,把前面的子串放到字典中,滑動到后面發(fā)現(xiàn)相同的子串時(shí)只需要替換成子串的位置和長度的信息進(jìn)去就行。
例如ABCDEFABCDZZZ → ABCDEF(6,4)ZZZ
意思是往前第6個(gè),長度為4。
當(dāng)然這只是簡單的一個(gè)體現(xiàn)思路的例子,實(shí)際中肯定沒有這么簡單,比如子串怎么找啊,滑動怎么滑等等之類的。
哈夫曼編碼
哈夫曼編碼,又涉及到哈夫曼樹,貪心算法。該方法完全依據(jù)字符出現(xiàn)概率來構(gòu)造異字頭的平均長度最短的碼字。
因?yàn)檫@個(gè)要根據(jù)字符出現(xiàn)的頻率構(gòu)建哈夫曼樹,不好簡單易懂的演示出來,這里就拿一個(gè)別人寫的Demo來直接演示效果。
原字符串:BCAADDDCCACACAC
轉(zhuǎn)成二進(jìn)制后:
10000100100001101000001010000010100010001000100010001000100001101000011010000010100001101000001010000110100000101000011
編碼后:1000111110110110100110110110
能看出壓縮的效果很明顯。
小結(jié)
Deflater算法是一種常用的數(shù)據(jù)壓縮算法,其內(nèi)部是使用LZ77和哈夫曼編碼。壓縮算法一般都具備平臺無關(guān)性,它是一種計(jì)算,一種思想,java使用的是Deflater這個(gè)類,php也有對應(yīng)的庫,go也有對應(yīng)的庫。甚至當(dāng)你知道了它的原理之后,你也能自己把實(shí)現(xiàn)過程給寫出來,當(dāng)然這很麻煩,畢竟涉及算法還是有一定難度。所以一般在開發(fā)中你得知道有這么一個(gè)東西,它是干嘛的,怎么使用。當(dāng)然最好還是能知道它的原理,知道它怎么實(shí)現(xiàn)的,這并不是毫無作用,當(dāng)你去學(xué)之后,你一定能收獲到一些東西。
可以再擴(kuò)展一下,像圖片的質(zhì)量壓縮,就是一種有損壓縮的方式,像視頻的H264編碼,H265編碼等,也是一個(gè)有損的過程。要心里有個(gè)底,對這個(gè)數(shù)據(jù)進(jìn)行操作,是否需要可逆,是否是針對它的大小,可逆就用無損壓縮的算法,為了極致的壓縮大小又無所謂不可逆,那就用有損壓縮的算法。對數(shù)據(jù)的傳輸是否要安全,全都無所謂就明文傳輸最快,對其大小有要求就壓縮,要求安全就加密。開發(fā)就這么簡單!
GZIP
GZIP也是一種壓縮技術(shù),相信很多人都聽說過。我們的http請求頭中可以配置content-encoding為gzip,那么服務(wù)端返回的數(shù)據(jù)就是經(jīng)過gzip壓縮過之后的數(shù)據(jù)。那有什么用呢?你文件大,字節(jié)數(shù)多,傳輸?shù)乃俣染吐?,我?jīng)過gizp壓縮之后,壓縮率高,傳輸?shù)淖止?jié)數(shù)少很多,那傳輸?shù)乃俣染涂臁?/p>
有的人也會說,那你壓縮可解壓也是耗時(shí)間的啊。說得好,這種我建議你不要信什么原理,直接去實(shí)踐,去試試使用GZIP壓縮和不使用韓國,誰得速度更快。當(dāng)然數(shù)據(jù)量大的情況下去測。你會發(fā)現(xiàn)哪怕我經(jīng)過壓縮和解壓,也比你直接傳輸?shù)乃俣雀臁?/p>
GZIP中的實(shí)現(xiàn)也包含了Deflater算法。所以能看出來,壓縮算法很多,基本都萬變不離其宗,基本都是靠LZ77和哈夫曼,為什么呢?因?yàn)閯e人好用啊,你寫不出比它更厲害的,那不用它的用什么。
以上就是Android 數(shù)據(jù)壓縮淺析的詳細(xì)內(nèi)容,更多關(guān)于Android 數(shù)據(jù)壓縮的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android中ScrollView監(jiān)聽滑動距離案例講解
這篇文章主要介紹了Android中ScrollView監(jiān)聽滑動距離案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Android程序自動更新功能模塊的實(shí)現(xiàn)方法【附完整demo源碼下載】
這篇文章主要介紹了Android程序自動更新功能模塊的實(shí)現(xiàn)方法,具備完整的自動檢測更新及下載、安裝等功能,并附帶完整的demo源碼供大家下載參考,需要的朋友可以參考下2016-08-08
第三方開源Android TickPlusDrawable狀態(tài)可以通過動畫切換的按鈕
Android tickplusdrawable(TickPlusDrawable)是一個(gè)狀態(tài)可以通過動畫切換的按鈕,本文給大家分享第三方開源Android TickPlusDrawable狀態(tài)可以通過動畫切換的按鈕,感興趣的朋友一起學(xué)習(xí)吧2015-12-12
unity5.6 導(dǎo)出gradle工程 Android Studio 導(dǎo)入問題及處理方法
這篇文章主要介紹了unity5.6 導(dǎo)出gradle工程 Android Studio 導(dǎo)入問題及處理方法,需要的朋友可以參考下2017-12-12
Android開發(fā)必備:秒殺真機(jī)超快模擬器Genymotion介紹
這篇文章主要介紹了Android開發(fā)必備:秒殺真機(jī)超快模擬器Genymotion介紹,本文直接用圖片說明Genymotion的安裝和模擬效果,并提供官網(wǎng),需要的朋友可以參考下2015-04-04
基于Android實(shí)現(xiàn)仿QQ5.0側(cè)滑
本課程將帶領(lǐng)大家通過自定義控件實(shí)現(xiàn)QQ5.0側(cè)滑菜單,課程將循序漸進(jìn),首先實(shí)現(xiàn)最普通的側(cè)滑菜單,然后引入屬性動畫與拖動菜單效果相結(jié)合,最終實(shí)現(xiàn)QQ5.0側(cè)滑菜單效果。通過本課程大家會對側(cè)滑菜單有更深層次的了解,通過自定義控件和屬性動畫打造千變?nèi)f化的側(cè)滑菜單效果2015-12-12
Android自定義帶動畫的半圓環(huán)型進(jìn)度效果
這篇文章主要為大家詳細(xì)介紹了Android自定義帶動畫的半圓環(huán)型進(jìn)度效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
Android實(shí)現(xiàn)系統(tǒng)狀態(tài)欄的隱藏和顯示功能
這篇文章主要介紹了Android實(shí)現(xiàn)系統(tǒng)狀態(tài)欄的隱藏和顯示功能,文中還給大家?guī)硭姆N方法,大家可以根據(jù)自己需要參考下2018-07-07

