偶然間注意到一個困擾了我很久的問題,那就是如果我不通過Socket而通過應用層的某種基于文本的協議,比如SOAP進行通信的話,
如何傳遞二進制的數據呢?現在SOA,Web Service等很火,應該會遇到這種問題吧?
現在已知的方法可以通過Base64進行編碼,其原理和方法見:
http://baike.baidu.com/view/469071.htm
這種方法采用了字節中的6位進行文本轉換,并且在其他論壇上也看到了帖子說淘寶的搜索也采用了這種編碼方式進行處理。
但是采用了5位進行轉換。并且大膽地給出了5位轉碼的算法,見:
http://www.javaeye.com/topic/286240
不過這種5位的轉換會產生更多多余的字節,6位的轉碼充分利用了現今的可讀文本,可是5位卻沒有,因為5和8的最小公倍數是40,
所以當每轉換40位即5個字節的二進制數據需要8個字節來表示,這樣就多產生3個字節,浪費的效率是3/5, 而6位轉碼浪費的效率是
1/3。而且隨著字節增多,轉化效率也在下降。可見采用5位轉碼是一種既浪費空間,又浪費效率的解決方案。在不增加url長度的情況下充分提高效率,6位編碼是最佳的。如果可以任意的餓犧牲url長度,
可以把0-9全部拿出來當做標記位,0-9不會單獨出現,這樣一共有10*26 + 26 = 286 種可能還不包括小寫字母,
此外還有=,+,-什么的至少256可以編碼8位的字節了,這樣處理效率就提高了。
現在把問題優化一下,人類可讀無歧義的文本碼有0-9,A-Z,a-z共62個
設取出x個作為標志位則(62-x) * x + (62 - x) >= 256
解這個二元一次方程得到:
3.366<=X<=57.634
考慮到編碼的文本長度,取x的最小值,即 4
最優解:
用0, 1, 2, 3做為標志位
4-9,A-Z, a-z參與編碼并與標志位配合實現8位字節的文本化
可以看到這種方法的轉碼效率會比較高,但是空間冗余大。
此外其實可用的文本不知62個,包括感嘆號等用上后補足64 = 2^6
它的高位是 00
那么只要再找到三個文本符保存其他三個高位01 10 11就可以了
這樣的轉碼空間可以更小一些。
想法還很不成熟,歡迎大家批評
@2008 楊一. 版權所有. 保留所有權利