1. 程式人生 > >SharedPreferences,使用base64編碼,儲存複雜物件

SharedPreferences,使用base64編碼,儲存複雜物件

SharedPreferences 使用base64儲存複雜物件

本篇博文建議電腦看,因為要對應碼錶,如果在小螢幕看起來會很(還沒想到修飾詞)

什麼是base64:

base64是編碼方式之一

什麼是編碼方式(base64):

編碼方式是資訊從一種格式轉換為另一種格式的過程
看到比較的多編碼方式有:ASCII,GBK,Unicode….

base64是為了解決什麼而出現的:

通俗的說就是以前的郵件網路傳送,只能傳送我們肉眼看到的字元,而看不到的字元不可以傳送,
比如換行符啊,空格,回車。為了解決傳送不了這些不可見字元,所以就出現了base64編碼方式。

我對base64的通俗理解:

base64其實就是使用了64個肉眼可以看到的字元來表示二進位制,而計算中的資料都是使用二進位制表示
通俗的說:就是使用64個看的到的字元表示了所有資料:包括肉眼可見的和肉眼不可見的

base64的64個字元是啥:(看圖,來自維基百科:https://en.wikipedia.org/wiki/Base64
可以看到value是0-63,char是”A-Z、a-z、0-9” 一個加號和一個斜杆(剛好總共64個)
這裡寫圖片描述

我理解的索引表(base64):
索引表都是約定俗成的,固定的value表示固定的char,就好像加法表一樣,1+1=2,這個是固定的了,解析不了為啥,比如:1+1=2

位元組和位(base64)

我們都知道一個位元組等於八位。而想表示base64索引表中的value:0-63,要多少位元組呢,答案:不需要一個位元組(8位),只需要6位就可以表示,
十進位制的0-63只要二進位制的111111(6位)就可以表示玩了

00000000 轉換為10進位制 0
00111111 轉換為10進位制 63

如何轉換為base64

字串轉為base64碼,需要把字元轉為ascll碼中的數字,然後再把數字轉換為二進位制,然後再轉base64

ASCII對照表(如果是直接輸入,然後查詢的,有的是錯的(2018/6/5),還是肉眼慢慢找吧) http://ascii.911cha.com/


這裡寫圖片描述

這裡寫圖片描述

下面來一些例子:

首先是我的名字:

字串: l i n x i n

ASCII 108 105 110 120 105 110
二進位制8位 0110 1100 0110 1001 0110 1110 0111 1000 0110 1001 0110 1110
011011000110100101101110011110000110100101101110
6位 011011 000110 100101 101110 011110 000110 100101 101110
十進位制 27 6 37 46 30 6 37 46
對應編碼 b G l u e G l u

這裡格式不好排,我上傳一張圖片
這裡寫圖片描述
啊哈哈,對著這些數字找對應編碼的時候,讓我想起了國民黨打仗發的電報(好像也是有一本這樣的索引表)


 //通過base64儲存複雜物件到SharedPreferences
 public static boolean saveObject(String key, Object obj, Context context) {
        //如果物件為null,不儲存,直接返回儲存失敗
        if (obj == null) {
            return false;
        }
        //flag,用於判斷是否儲存物件成功
        boolean flag = false;
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        // 內部建立一個byte型別陣列的緩衝區,最初預設為32位,在需要的時候會自動增加大小,從流中讀位元組陣列
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        //主要的作用是用於寫入物件資訊與讀取物件資訊
        ObjectOutputStream objectOutputStream = null;
        try {
            // 建立物件輸出流,並封裝位元組流
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            // 將物件寫入位元組流
            objectOutputStream.writeObject(obj);
            // 將位元組流編碼成base64的字元竄
            String base64String = new String(Base64.encode(byteArrayOutputStream
                    .toByteArray(), Base64.DEFAULT));
            flag = preferences.edit().putString(key, base64String).commit();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //主要做關閉流操作
            try {
                if (objectOutputStream != null) {
                    objectOutputStream.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return flag;
        }
    }
//讀取複雜物件
    public static Object getObject(String key, Context context) {
        Object obj = null;
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        String objString = preferences.getString(key, "");
        // 讀取位元組
        byte[] base64 = Base64.decode(objString.getBytes(), Base64.DEFAULT);
        // 位元組流
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(base64);
        //物件流
        ObjectInputStream objectInputStream = null;
        try {
            // 再次封裝
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            // 讀取物件
            obj = objectInputStream.readObject();
        } catch (Exception e) {
            // e.printStackTrace();
        } finally {
            try {
                if (objectInputStream != null) {
                    objectInputStream.close();
                }

                if (byteArrayInputStream != null) {
                    byteArrayInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return obj;
    }


//序列化的實體類
class Person implements Serializable {
    private String firstName;
    private String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return lastName+firstName;
    }
}
//簡單用例
public class MainActivity extends AppCompatActivity {

    private static final String KEY = "key";
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Person p = new Person("lin", "xin");
        if (saveObject(KEY, p, this)) {
            Log.i(TAG, getObject(KEY, this).toString());
        } else {
            Log.i(TAG, "onCreate:失敗 ");
        }
    }

}