Android的儲存----重新認識Android(9)

AND_YOU_with_ME發表於2017-04-14
安卓的(持久化)儲存機制:
1.共享引數儲存SharedPreferences,一遍用於儲存簡單的鍵值對的配置資訊,使用者名稱....
鍵值對的值限於int,long,String,float,boolean
2.內部儲存Internal Storage,即存在手機的記憶體中.一遍用於存放一下不太大的檔案.
手機儲存:
RAM:執行時記憶體.相當於pc機的記憶體,不是持久化儲存的,裡面的資料斷點就消失.
ROM:相當於pc機的硬碟
SD CARD:擴充套件儲存卡.

SharedPreferences共享引數
 
一、資料儲存選項:Data Storage ——Storage Options
1、Shared Preferences 
Store private primitive data in key-value pairs.
儲存簡單的鍵值對資料。
2、Internal Storage
Store private data on the device memory.
在手機記憶體中儲存不對外共享的資訊。
3、External Storage
Store public data on the shared external storage.
在外部儲存裝置上儲存公共的資料資訊。主要指儲存在SDCard上。
4、SQLite Databases
Store structured data in a private database.
將結構化的資料儲存進資料庫。
 
二、SharedPreferences:
(一)、概念:
        SharedPreferences是Android系統提供的一個通用的資料持久化框架,用於儲存和讀取key-value型別的原始基本資料型別的資料,目前支援String、int、long、float、boolean等基本型別的儲存,對於自定義的物件資料型別,無法使用SharedPreferences來儲存。
        SharedPreferences主要用於儲存系統的配置資訊。例如上次登入的使用者名稱,上次最後設定的配置資訊(如:是否開啟音效、是否使用振動,小遊戲的玩家積分等)。當再次啟動程式後依然保持原有設定。SharedPreferences用鍵值對方式儲存,方便寫入和讀取。
 
(二)、使用SharedPreferences的步驟:
1、獲取SharedPreferences物件;
        SharedPreferences本身是一個介面,無法直接建立例項,通過Context中定義的例項方法
getSharedPreferences(String name, int  mode)方法來獲取例項。
        該方法的第二個參數列示檔案讀寫的操作模式,傳入:
Context.MODE_PRIVATE:  指定該SharedPreferences的資料只能被本應用程式讀、寫;
2、呼叫edit()方法獲取SharedPreferences.Editor介面型別的物件;
3、通過SharedPreferences.Editor介面提供的putXxx(...)方法對SharedPreferences進行更新;
4、呼叫SharedPreferences.Editor的commit()方法,將更新提交到SharedPreferences中。
clear()方法,清空已有的所有共享引數,但不清除editor裡面的資料(在commit()之後能寫出去)
      5、呼叫SharedPreferences的getXxx(String key,Xxx defaultValue)方法獲取指定key的value
SharedPreferences的其他常用方法:
    boolean contains(String key)判斷是否包含指定鍵的資料
    Map<String,?> getAll()獲取所有的鍵值對, 需要物件造型: Map<String,Object> map = (Map<String,Object>)sp.getAll();
核心程式碼:
核心程式碼:
public void click(View v) {
     if (v.getId() == R.id.bt_save) {// 儲存共享引數
     //要儲存,必須先獲取Editor物件
     Editor editor = sp.edit();
      // editor.putString("name", et_name.getText().toString());
       // editor.putString("phone", et_phone.getText().toString());
       editor.putString("test", "aaaaaaaaa");
       editor.clear();//清空已有的所有共享引數,再把editor裡面的資料寫出去
       editor.commit();//提交
       Toast.makeText(this, "儲存成功!", 0).show();
     } else { // 讀取共享引數
        // String name = sp.getString("name", "預設           值-無名氏");
         // String phone = sp.getString("phone", "000000");
          // tv_showData.setText("name:"+name+",phone:"+phone);
           Map<String,?> map = sp.getAll();
           Set<String> keys = map.keySet();
           StringBuilder sb = new StringBuilder();
           for(String aKey :keys){
                Object obj = map.get(aKey);
                sb.append(aKey).append("=").append(obj).append('\t');
          }
       tv_showData.setText(sb);
    }
}
(四)、儲存之後的SharedPreferences資料檔案:
        SharedPreferences資料總是以xml格式儲存在:/data/data/包名/shared_prefs/{檔名};
Cd D:\workspace\sdk\platform-tools------------adb所在的目錄
adb shell
cd /data/data/包名/shared_prefs
ls 檢視所有的目錄
cat person.xml
檔案格式如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="pwd">123456</string>
    <string name="username">xiangjun</string>
    <int  name="age">20</int>
</map>
------------------------------------------------------------------
內部儲存Internal Storage
檔案儲存路徑:
/data/data/包名/files/{檔名}
Context的例項方法(Activity中繼承過來了):
 FileOutputStream openFileOutput (String filename, int mode)//用追加或覆蓋的模式, 獲得檔案輸出流, 可以寫出到指定檔名的檔案
  mode的取值:
  Context.MODE_APPEND追加模式,不寫就是覆蓋模式
  Context.MODE_PRIVATE
       中間可以用 | 或者 + 來連線
十進位制12===>二進位制00000000000001100
十進位制5  ===>二進位制00000000000000101
int k = 12&5;   //4
int m = 12|5;   //13
i:二進位制00000000000001000
j:二進位制00000000000000100
int k = i  | j;//12
int m = i+j;//12
 
Context的例項方法:
 FileInputStream openFileInput (String filename) 該方法應寫在事件處理方法裡面
 String[] fileList()列出所有的檔名陣列
 boolean deleteFile(String filename)刪除指定檔名的檔案
[ 案例:]
點選按鈕A從UI上獲取使用者名稱和手機號,儲存到內部儲存的檔案中;
點選按鈕B從內部儲存中取出顯示在文字框中
  ----------------------------------------------------
External Storage之SDCard操作:
(一)、引入:
畢竟手機內建儲存空間很有限, 記憶體卡中可能空間不夠,為了更好地儲存應用程式的大檔案資料,需要讀寫SD卡上的檔案。SD卡大大擴充了手機的儲存能力。
 
(二)、讀寫SD卡的步驟:
1、先判斷手機是否有sd卡:
     呼叫Environment的靜態方法 StringgetExternalStorageState()方法判斷手機是否插上sdcard。得到的結果可能有:
Environment.MEDIA_MOUNTED介質已載入完
Environment.MEDIA_MOUNTED_READ_ONLY 介質已載入完,但是隻讀狀態
Environment.MEDIA_CHECKING 正在檢測介質
Environment.MEDIA_UNKNOWN  介質未知
Environment.MEDIA_UNMOUNTED 介質已解除安裝
2、獲取sdcard的路徑;
        呼叫Environment靜態方法StringgetExternalStorageDirectory()方法來獲取外部儲存器的目錄。
3、此外還可以獲取SDCard可用磁碟空間的大小(藉助StatFs類來實現);
4、清單檔案中設定讀寫sdcard的許可權;
  <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>   允許掛載和反掛載檔案系統可移動儲存
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
5、執行讀寫操作(基本IO流操作)。
 
(三)、封裝SDCard的工具類:SDCardHelper類
判斷sdcard是否掛載
boolean isSDCardMounted()
    getExternalStorageState()
    Environment.MEDIA_MOUNTED
獲取sdcard絕對物理路徑
String getSDCardPath()
    getExternalStorageDirectory()
獲取sdcard的全部的空間大小。返回MB位元組
long getSDCardSize()  
    new StatFs(getSDCardPath());
    sf.getBlockSize();//獲取每塊的大小
    sf.getBlockCount();//獲取總塊數
獲取sdcard的剩餘空間的大小。返回MB位元組
long getSDCardFreeSize()
    sf.getFreeBlocks();//獲取空閒的塊數
獲取SD卡的可用空間大小,返回MB
long getSDCardAvailableSize()
    sf.getAvailableBlocks();//獲取可用空間的大小
將檔案(byte[])儲存進sdcard指定的路徑下  dir:指定的路徑
boolean saveFileToSDCard(byte[] data, String dir,String filename) 
已知檔案的絕對路徑,從sdcard中獲取到該檔案,返回byte[].    
byte[] loadFileFromSDCard(String filepath)
public class SDCardHelper {
    private static String TAG = "SDCardHelper";

    /**
     * 判斷sdcard是否掛載
     */
    public static boolean isSDCardMounted() {
        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    }

    /**
     * 獲取sdcard絕對物理路徑 得到的格式為 /storage/sdcard 後面沒有斜線
     */
    public static String getSDCardPath() {
        if (isSDCardMounted()) {
            return Environment.getExternalStorageDirectory().getAbsolutePath();
        } else {
            return null;
        }
    }

    /**
     * 獲取sdcard的全部的空間大小。返回MB位元組
     */
    public static long getSDCardSize() {
        if (isSDCardMounted()) {
            StatFs fs = new StatFs(getSDCardPath());
// 因為帶有Long結尾的替代方法需要API 18以上的SDK才能支援,所以,暫時使用舊的
            long size = fs.getBlockSize();
            long count = fs.getBlockCount();// 獲取總塊數
            return size * count / 1024 / 1024;
        }
        return 0;
    }

    /**
     * 獲取sdcard的剩餘空間的大小。返回MB位元組
     */
    public static long getSDCardFreeSize() {
        if (isSDCardMounted()) {
            StatFs fs = new StatFs(getSDCardPath());
            long size = fs.getBlockSize();
            long count = fs.getFreeBlocks();// 獲取空閒的塊數
            return size * count / 1024 / 1024;
        }
        return 0;
    }

    /**
     * 獲取SD卡的可用空間大小,返回MB
     *
     * @return
     */
    public static long getSDCardAvailableSize() {
        if (isSDCardMounted()) {
            StatFs fs = new StatFs(getSDCardPath());
            int count = fs.getAvailableBlocks();// 獲取可用空間的大小
            int size = fs.getBlockSize();
            return count * size / 1024 / 1024;
        }
        return 0;
    }

    /**
     * 將檔案(byte[])儲存進sdcard指定的路徑下 dir:指定的路徑
     */
    public static boolean saveFileToSDCard(byte[] data, String dir, String filename) {
        BufferedOutputStream bos = null;
        if (isSDCardMounted()) {
            Log.i(TAG, "==isSDCardMounted==TRUE");
            File file = new File(getSDCardPath() + File.separator + dir);
            Log.i(TAG, "==file:" + file.toString() + file.exists());
            if (!file.exists()) {
                boolean flags = file.mkdirs();
                Log.i(TAG, "==建立資料夾:" + flags);
            }
            try {
                bos = new BufferedOutputStream(new FileOutputStream(new File(file, filename)));
                bos.write(data, 0, data.length);
                bos.flush();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    /**
     * 已知檔案的絕對路徑,從sdcard中獲取到該檔案,返回byte[]
     */
    public static byte[] loadFileFromSDCard(String filepath) {
        BufferedInputStream bis = null;
        ByteArrayOutputStream baos = null;
        if (isSDCardMounted()) {
            File file = new File(filepath);
            if (file.exists()) {
                try {
                    baos = new ByteArrayOutputStream();
                    bis = new BufferedInputStream(new FileInputStream(file));
                    byte[] buffer = new byte[1024 * 8];
                    int c = 0;
                    while ((c = bis.read(buffer)) != -1) {
                        baos.write(buffer, 0, c);
                        baos.flush();
                    }
                    return baos.toByteArray();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (bis != null) {
                            bis.close();
                            baos.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }
    
}



相關文章