json傳輸二進位制的方案

NO IMAGE

本文轉自:http://wiyi.org/binary-to-string.html

json 是一種很簡潔的協議,但可惜的是,它只能傳遞基本的數型(int,long,string等),但不能傳遞byte型別。如果想要傳輸圖片等二進位制檔案的話,是沒辦法直接傳輸。

本文提供一種思路給大家參考,讓大家可以在json傳輸二進位制檔案,如果大家有這個需求又不知怎麼實現的話,也許本文能夠幫到你。思想適用於所有語言,本文以java實現,相信大家很容易就能轉化為自己懂得語言。

思路

1. 讀取二進位制檔案到記憶體

2. 用Gzip壓縮一下。畢竟是在網路傳輸嘛,當然你也可以不壓縮。

3. 用Base64 把byte[] 轉成字串

補充:什麼是Base64

以下摘自阮一峰部落格,Base64的具體編碼方式,大家可以直接進入

Base64是一種編碼方式,它可以將8位的非英語字元轉化為7位的ASCII字元。這樣的初衷,是為了滿足電子郵件中不能直接使用非ASCII碼字元的規定,但是也有其他重要的意義:

a)所有的二進位制檔案,都可以因此轉化為可列印的文字編碼,使用文字軟體進行編輯;

b)能夠對文字進行簡單的加密。

實現

主要思路就是以上3步,把字串新增到json欄位後發給服務端,然後伺服器再用Base64解密–>Gzip解壓,就能得到原始的二進位制檔案了。是不是很簡單呢?說了不少,下面我們來看看具體的程式碼實現。

***注:Java SE是沒辦法直接用Base64的哦,必須要先自己去下載一份。但Android已經整合了Base64,因此大家可以直接在Android使用。

/**
* @author xing
*/
public class TestBase64 {
public static void main(String[] args) {
byte[] data = compress(loadFile());
String json = new String(Base64.encodeBase64(data));
System.out.println("data length:"   json.length());
}
/**
* 載入本地檔案,並轉換為byte陣列
* @return
*/
public static byte[] loadFile() {
File file = new File("d:/11.jpg");
FileInputStream fis = null;
ByteArrayOutputStream baos = null;
byte[] data = null ;
try {
fis = new FileInputStream(file);
baos = new ByteArrayOutputStream((int) file.length());
byte[] buffer = new byte[1024];
int len = -1;
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
data = baos.toByteArray() ;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
fis = null;
}
baos.close() ;
} catch (IOException e) {
e.printStackTrace();
}
}
return data ;
}
/**
* 對byte[]進行壓縮
* 
* @param 要壓縮的資料
* @return 壓縮後的資料
*/
public static byte[] compress(byte[] data) {
System.out.println("before:"   data.length);
GZIPOutputStream gzip = null ;
ByteArrayOutputStream baos = null ;
byte[] newData = null ;
try {
baos = new ByteArrayOutputStream() ;
gzip = new GZIPOutputStream(baos);
gzip.write(data);
gzip.finish();
gzip.flush();
newData = baos.toByteArray() ;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
gzip.close();
baos.close() ;
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("after:"   newData.length);
return newData ;
}
}

最後輸出了一下字串長度,大家也許覺得經過壓縮也沒降低多少體積嘛。但大家可以試試不用gzip,你會發現經過轉換的字串比原來大多了。沒辦法,這是由Base64的演算法決定的。所以嘛,還是壓縮一下好。

本文所使用的方法比較簡單,大家如果有更好或者覺得有更好的方式,不妨一起探討一下。

最後順便吐槽一下Java,竟然寫了這麼多行程式碼。要是用Python,估計沒幾行就能搞定了。