無論是神馬平台,神馬開發環境,神馬軟件程序,數據都是核心。對於開發平台來講,如果對數據的存儲有良好的支持,那麼對應用程序的開發將會有很大的促進作用。
總體的來講,數據存儲方式有三種:一個是文件,一個是數據庫,另一個則是網絡。其中文件和數據庫可能用的稍多一些,文件用起來較為方便,程序可以自己定義格式;數據庫用起稍煩鎖一些,但它有它的優點,比如在海量數據時性能優越,有查詢功能,可以加密,可以加鎖,可以跨應用,跨平台等等;網絡,則用於比較重要的事情,比如科研,勘探,航空等實時采集到的數據需要馬上通過網絡傳輸到數據處理中心進行存儲並進行處理。
對於Android平台來講,它的存儲方式也不外乎這幾種,按方式總體來分,也是文件,數據庫和網絡。但從開發者的角度來講它可以分為以下五種方式:
- SharedPreferences共享偏好
- Internal Storage內部存儲空間
- External Storage外部存儲空間
- SQLite Database數據庫
- Internet網絡
這幾種方式各自有各自的優點和缺點,要根據不同的實際情況來選擇,而無法給出統一的標准。下面就各種方式談談它們的優缺點,以及最合適的使用情況:
- Shared Preferences共享偏好
SharedPreferences是用來存儲一些Key/Value類似的成對的基本數據類型,注意,它只能存儲基本數據類型,也即int, long, boolean, String, float。事實上它完全相當於一個HashMap,唯一不同的就是HashMap中的Value可以是任何對象,而SharedPreferences中的值只能存儲基本數據類型(primitive types)。
對於它的使用方法,可以參考Android Developer Guide,這裡不重復。
如此來看,最適合SharedPreferences的地方就是保存配置信息,因為很多配置信息都是Key/Value。事實上,在Android當中SharedPreferences使用最多的地方也是用來保存配置(Settings)信息,系統中的Settings中這樣,各個應用中的Settings也是這樣。並且,Android中為了方便的使用SharedPreferences保存配置信息,它來專門有PreferenceActivity用來封裝。也就是說如果你想在應用程序中創建配置(Settings),你可以直接使用PreferenceActivity和一些相關的專門為Preference封裝的組件,而不用再直接去創建,讀取和保存SharedPreference,Framework中的這些組件會為你做這些事。
再談談一些使用SharedPreference時的技巧,它只能保存基本數據類型,但假如我想保存一個數組,怎麼辦?可以把數據進行處理,把它轉化成一個String,取出的時候再還原就好了;再如,如想保存一個對象,怎麼辦,同樣,可以把對象序列化成為字符序列,或轉成String(Object.toString()),或是把它的HashCode(Object.hashCode())當成Value保存進去。
總之,SharedPreferences使用起來十分的方便,可以靈活應用,因為它簡單方便,所以能用它就盡量不要用文件或是數據庫。
- Internal Storage內部存儲空間
所謂的內部存儲與外部存儲,是指是否是手機內置。手機內置的存儲空間,稱為內部存儲,它是手機一旦出廠就無法改變,它也是手機的硬件指標之一,通常來講手機內置存儲空間越大意味著手機價格會越貴(很多地方把它稱為手機內存,但我們做軟件的知道,這並不准確,內存是指手機運行時存儲程序,數據和指令的地方;這裡應該是手機內部存儲的簡稱為內存,而並非嚴格意義上的內存)。
內部存儲空間十分有限,因而顯得可貴,所以我們要盡可能避免使用;另外,它也是系統本身和系統應用程序主要的數據存儲所在地,一旦內部存儲空間耗盡,手機也就無法使用了。所以對於內部存儲空間,我們要盡量避免使用。上面所談到的Shared Preferences和下面要談到的SQLite數據庫也都是存儲在內部存儲空間上的。
Android本身來講是一個Linux操作系統,所以它的內部存儲空間,對於應用程序和用戶來講就是“/data/data"目錄。它與其他的(外部的存儲)相比有著比較穩定,存儲方便,操作簡單,更加安全(因為可以控制訪問權限)等優點。而它唯一的缺點就是它比較有限,比較可貴。
雖然,可以非常容易的知道程序本身的數據所在路徑,所有的應用程序的數據路徑都是“/data/data/app-package-name/”,所有的程序用到的數據,比如libs庫,SharedPreferences都是存放在這個路徑下面。但我們在使用的時候最好不要,或是千萬不要直接引用這個路徑。
使用內部存儲主要有二個方式,一個是文件操作,一個是文件夾操作。無論哪種方式,Context中都提供了相應的函數來支持,使用Context不但操作簡單方便,最重要的是Context會幫助我們管理這些文件,也可以方便幫助我們控制文件的訪問權限。先來系統的說下Context中關於文件和文件夾操作的函數有哪些。
a. 創建一個文件,並打開成一個文件輸出流,需要提供一個String,作為文件名
- FileOutputStream output = Context.openOutputFile(filename, Context.MODE_PRIVATE);
- output.write(data);// use output to write whatever you like
- output.close();
- FileOutputStream output = Context.openOutputFile(filename, Context.MODE_PRIVATE); output.write(data);// use output to write whatever you like output.close();
b. 同樣,想打開一個文件作為輸入的話,也是只需要提供文件名
- FileInputStream input = Context.openInputFile(filename);
- input.read();
- input.close();
- FileInputStream input = Context.openInputFile(filename); input.read(); input.close();
c. 列出所有的已創建的文件
- String[] files = Context.fileList();
- for (String file : files) {
- Log.e(TAG, "file is " + file);
- }
- String[] files = Context.fileList(); for (String file : files) { Log.e(TAG, "file is " + file); }
d. 刪除文件,能創建就要能夠刪除,當然也會提供了刪除文件的接口,它也非常簡單,只需要提供文件名
- if (Context.deleteFile(filename)) {
- Log.e(TAG, "delete file " + filename + " sucessfully“);
- } else {
- Log.e(TAG, "failed to delete file " + filename);
- }
- if (Context.deleteFile(filename)) { Log.e(TAG, "delete file " + filename + " sucessfully“); } else { Log.e(TAG, "failed to delete file " + filename); }
e. 獲取文件已創建文件的路徑,它返回一個文件對象用於操作路徑
- File fileDir = Context.getFileDir();
- Log.e(TAG, "fileDir " + fileDir.getAbsolutePath();
- File fileDir = Context.getFileDir(); Log.e(TAG, "fileDir " + fileDir.getAbsolutePath();
f. 創建一個目錄,需要傳入目錄名稱,它返回 一個文件對象用到操作路徑
- File workDir = Context.getDir(dirName, Context.MODE_PRIVATE);
- Log.e(TAG, "workdir " + workDir.getAbsolutePath();
- File workDir = Context.getDir(dirName, Context.MODE_PRIVATE); Log.e(TAG, "workdir " + workDir.getAbsolutePath();
g. 以File對象方式查看所創建文件,需要傳入文件名,會返回文件對象
- File store = Context.openFileStreamPath(filename);
- Log.e(TAG, "store " + store.length());
- File store = Context.openFileStreamPath(filename); Log.e(TAG, "store " + store.length());
h. 獲取Cache路徑,無需要傳入參數,返回文件對象
- File cachedir = Context.getCacheDir();
- Log.e(TAG, "cachedir " + cacheDir.getAbsolutePath());
- File cachedir = Context.getCacheDir(); Log.e(TAG, "cachedir " + cacheDir.getAbsolutePath());
總結一下文件相關操作,可以得出以下三個特點:
1. 文件操作只需要向函數提供文件名,所以程序自己只需要維護文件名即可;
2. 不用自己去創建文件對象和輸入、輸出流,提供文件名就可以返回File對象或輸入輸出流
3. 對於路徑操作返回的都是文件對象。