Android開發(fā)筆記之: 數(shù)據(jù)存儲方式詳解
更新時間:2013年05月23日 09:36:51 作者:
本篇文章是對Android中數(shù)據(jù)存儲方式進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
無論是神馬平臺,神馬開發(fā)環(huán)境,神馬軟件程序,數(shù)據(jù)都是核心。對于開發(fā)平臺來講,如果對數(shù)據(jù)的存儲有良好的支持,那么對應(yīng)用程序的開發(fā)將會有很大的促進(jìn)作用。
總體的來講,數(shù)據(jù)存儲方式有三種:一個是文件,一個是數(shù)據(jù)庫,另一個則是網(wǎng)絡(luò)。其中文件和數(shù)據(jù)庫可能用的稍多一些,文件用起來較為方便,程序可以自己定義格式;數(shù)據(jù)庫用起稍煩鎖一些,但它有它的優(yōu)點,比如在海量數(shù)據(jù)時性能優(yōu)越,有查詢功能,可以加密,可以加鎖,可以跨應(yīng)用,跨平臺等等;網(wǎng)絡(luò),則用于比較重要的事情,比如科研,勘探,航空等實時采集到的數(shù)據(jù)需要馬上通過網(wǎng)絡(luò)傳輸?shù)綌?shù)據(jù)處理中心進(jìn)行存儲并進(jìn)行處理。
對于Android平臺來講,它的存儲方式也不外乎這幾種,按方式總體來分,也是文件,數(shù)據(jù)庫和網(wǎng)絡(luò)。但從開發(fā)者的角度來講它可以分為以下五種方式:
1.SharedPreferences共享偏好
2.Internal Storage內(nèi)部存儲空間
3.External Storage外部存儲空間
4.SQLite Database數(shù)據(jù)庫
5.Internet網(wǎng)絡(luò)
這幾種方式各自有各自的優(yōu)點和缺點,要根據(jù)不同的實際情況來選擇,而無法給出統(tǒng)一的標(biāo)準(zhǔn)。下面就各種方式談?wù)勊鼈兊膬?yōu)缺點,以及最合適的使用情況:
1.Shared Preferences共享偏好
SharedPreferences是用來存儲一些Key/Value類似的成對的基本數(shù)據(jù)類型,注意,它只能存儲基本數(shù)據(jù)類型,也即int, long, boolean, String, float。事實上它完全相當(dāng)于一個HashMap,唯一不同的就是HashMap中的Value可以是任何對象,而SharedPreferences中的值只能存儲基本數(shù)據(jù)類型(primitive types)。
對于它的使用方法,可以參考Android Developer Guide,這里不重復(fù)。
如此來看,最適合SharedPreferences的地方就是保存配置信息,因為很多配置信息都是Key/Value。事實上,在Android當(dāng)中SharedPreferences使用最多的地方也是用來保存配置(Settings)信息,系統(tǒng)中的Settings中這樣,各個應(yīng)用中的Settings也是這樣。并且,Android中為了方便的使用SharedPreferences保存配置信息,它來專門有PreferenceActivity用來封裝。也就是說如果你想在應(yīng)用程序中創(chuàng)建配置(Settings),你可以直接使用PreferenceActivity和一些相關(guān)的專門為Preference封裝的組件,而不用再直接去創(chuàng)建,讀取和保存SharedPreference,F(xiàn)ramework中的這些組件會為你做這些事。
再談?wù)勔恍┦褂肧haredPreference時的技巧,它只能保存基本數(shù)據(jù)類型,但假如我想保存一個數(shù)組,怎么辦?可以把數(shù)據(jù)進(jìn)行處理,把它轉(zhuǎn)化成一個String,取出的時候再還原就好了;再如,如想保存一個對象,怎么辦,同樣,可以把對象序列化成為字符序列,或轉(zhuǎn)成String(Object.toString()),或是把它的HashCode(Object.hashCode())當(dāng)成Value保存進(jìn)去。
總之,SharedPreferences使用起來十分的方便,可以靈活應(yīng)用,因為它簡單方便,所以能用它就盡量不要用文件或是數(shù)據(jù)庫。
1.Internal Storage內(nèi)部存儲空間
所謂的內(nèi)部存儲與外部存儲,是指是否是手機內(nèi)置。手機內(nèi)置的存儲空間,稱為內(nèi)部存儲,它是手機一旦出廠就無法改變,它也是手機的硬件指標(biāo)之一,通常來講手機內(nèi)置存儲空間越大意味著手機價格會越貴(很多地方把它稱為手機內(nèi)存,但我們做軟件的知道,這并不準(zhǔn)確,內(nèi)存是指手機運行時存儲程序,數(shù)據(jù)和指令的地方;這里應(yīng)該是手機內(nèi)部存儲的簡稱為內(nèi)存,而并非嚴(yán)格意義上的內(nèi)存)。
內(nèi)部存儲空間十分有限,因而顯得可貴,所以我們要盡可能避免使用;另外,它也是系統(tǒng)本身和系統(tǒng)應(yīng)用程序主要的數(shù)據(jù)存儲所在地,一旦內(nèi)部存儲空間耗盡,手機也就無法使用了。所以對于內(nèi)部存儲空間,我們要盡量避免使用。上面所談到的Shared Preferences和下面要談到的SQLite數(shù)據(jù)庫也都是存儲在內(nèi)部存儲空間上的。
Android本身來講是一個Linux操作系統(tǒng),所以它的內(nèi)部存儲空間,對于應(yīng)用程序和用戶來講就是“/data/data"目錄。它與其他的(外部的存儲)相比有著比較穩(wěn)定,存儲方便,操作簡單,更加安全(因為可以控制訪問權(quán)限)等優(yōu)點。而它唯一的缺點就是它比較有限,比較可貴。
雖然,可以非常容易的知道程序本身的數(shù)據(jù)所在路徑,所有的應(yīng)用程序的數(shù)據(jù)路徑都是“/data/data/app-package-name/”,所有的程序用到的數(shù)據(jù),比如libs庫,SharedPreferences都是存放在這個路徑下面。但我們在使用的時候最好不要,或是千萬不要直接引用這個路徑。
使用內(nèi)部存儲主要有二個方式,一個是文件操作,一個是文件夾操作。無論哪種方式,Context中都提供了相應(yīng)的函數(shù)來支持,使用Context不但操作簡單方便,最重要的是Context會幫助我們管理這些文件,也可以方便幫助我們控制文件的訪問權(quán)限。先來系統(tǒng)的說下Context中關(guān)于文件和文件夾操作的函數(shù)有哪些。
a. 創(chuàng)建一個文件,并打開成一個文件輸出流,需要提供一個String,作為文件名
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();
c. 列出所有的已創(chuàng)建的文件
String[] files = Context.fileList();
for (String file : files) {
Log.e(TAG, "file is " + file);
}
d. 刪除文件,能創(chuàng)建就要能夠刪除,當(dāng)然也會提供了刪除文件的接口,它也非常簡單,只需要提供文件名
if (Context.deleteFile(filename)) {
Log.e(TAG, "delete file " + filename + " sucessfully“);
} else {
Log.e(TAG, "failed to delete file " + filename);
}
e. 獲取文件已創(chuàng)建文件的路徑,它返回一個文件對象用于操作路徑
File fileDir = Context.getFileDir();
Log.e(TAG, "fileDir " + fileDir.getAbsolutePath();
f. 創(chuàng)建一個目錄,需要傳入目錄名稱,它返回 一個文件對象用到操作路徑
File workDir = Context.getDir(dirName, Context.MODE_PRIVATE);
Log.e(TAG, "workdir " + workDir.getAbsolutePath();
g. 以File對象方式查看所創(chuàng)建文件,需要傳入文件名,會返回文件對象
File store = Context.openFileStreamPath(filename);
Log.e(TAG, "store " + store.length());
h. 獲取Cache路徑,無需要傳入?yún)?shù),返回文件對象
File cachedir = Context.getCacheDir();
Log.e(TAG, "cachedir " + cacheDir.getAbsolutePath());
總結(jié)一下文件相關(guān)操作,可以得出以下三個特點:
1. 文件操作只需要向函數(shù)提供文件名,所以程序自己只需要維護(hù)文件名即可;
2. 不用自己去創(chuàng)建文件對象和輸入、輸出流,提供文件名就可以返回File對象或輸入輸出流
3. 對于路徑操作返回的都是文件對象。
如前所述,內(nèi)部存儲空間有限,可貴,安全,穩(wěn)定,所以應(yīng)該用來保存比較重要的數(shù)據(jù),比如用戶信息資料,口令秘碼等不需要與其他應(yīng)用程序共享的數(shù)據(jù)。也可以用來創(chuàng)建臨時文件,但一定要注意及時刪除。另外,對于內(nèi)部存儲還有一個非常重要的特點,那就是在應(yīng)用程序被卸載時,應(yīng)用程序在內(nèi)部存儲空間的文件數(shù)據(jù)將全部被刪除。系統(tǒng)這樣做的原因很簡單,就是因為內(nèi)部存儲很有限,它必須保證它的可用性,因為一旦添滿,系統(tǒng)將無法再正常工作。
1.External Storage外部存儲空間
再來談?wù)勈謾C外部存儲空間,與內(nèi)部存儲空間相對,外部存儲空間是指手機出廠的時候不存在,用戶在使用時候可以自由添加的外部存儲介質(zhì)比如TS卡,SD卡等閃存儲介質(zhì)。這些閃存介質(zhì)由最初的空間小價格貴,到現(xiàn)在的大容量價格便宜,所以幾乎每個支持外部存儲的手機上面都有大容量(大于等于2G)的閃存卡。
Android也是不例外,它完全支持外部存儲介質(zhì)。其實更確切的說,它是要依賴于外部存儲卡的,因為對于Android系統(tǒng),如果沒有外部存儲卡,很多的系統(tǒng)應(yīng)用無法使用,比如多媒體相關(guān)的應(yīng)用程序無法使用。雖然Android很依賴,但是外部存儲卡也有它自身的特點,它最大的優(yōu)點就是存儲空間大,基本上你可無限制的使用,也不怎么擔(dān)心去清除數(shù)據(jù)。就目前來看,很多程序都在使用外部存儲卡,但很少有程序去主動清理數(shù)據(jù),所以無論你的SD卡有多大,它的可用空間卻越來越少。與內(nèi)部存儲不同的是,當(dāng)程序卸載時,它在外部存儲所創(chuàng)建的文件數(shù)據(jù)是不會被清除的。所以清理外部存儲空間的責(zé)任丟給了用戶自己,每隔一段時間就去查看下SD卡,發(fā)現(xiàn)無用數(shù)據(jù)立馬刪除。外部存儲的缺點就是不是很穩(wěn)定,對于Android手機來講可以說,很不穩(wěn)定,本身閃存介質(zhì)就容易出問題,SD卡處于不能正常使用的狀態(tài)十分多。
先來說說外部存儲相關(guān)的使用方法和API:
a. Check media availability檢查介質(zhì)的可用性
如前所述,外部存儲介質(zhì)的穩(wěn)定性十分的差,所以在使用之前一定要先檢查它的可用性,如果可用再去用
final String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED) || state.equals(Environment.MEDIA_READ_ONLY)) {// sd card is ready to us }
b. Get the directory獲取外部存儲卡的路徑
事實上,外部存儲卡的路徑是“/mnt/sdcard",所以你直接這樣寫去訪問也能訪問的到。鑒于可讀性和可移植性的考慮,建議這樣寫:
File sdcardDir = Environment.getExternalStorageDirectory();
c. For API 8 or greater, there are some other useful APIs helping to manager files and directories.
如果你使用API 8(Android 2.2)或者更高,那么SDK中又多了幾個操作外部存儲文件和路徑的接口,文檔中也建議開始者更加規(guī)范的使用SD卡。比如,創(chuàng)建相應(yīng)的目錄去存儲相應(yīng)的數(shù)據(jù),Music,Picture,Video等。應(yīng)用程序目錄也變成了"/Android/data/package-name/data"。具體的使用可以參考文檔,這里不重復(fù)。當(dāng)然,就像編程規(guī)范一樣,這里只是規(guī)范,你完全可以不遵守它,但出于可讀性和可移植性,還是建議按照文檔建議的去做。
下面總結(jié)一下使用時應(yīng)該注意的一些和外部存儲的特點:
a. 外部存儲卡不是隨時想用就能夠用的,所以一定要記得在使用之前檢查它的可用性
b. 存儲在外部存儲卡上的數(shù)據(jù)是所有應(yīng)用程序都可見,用戶也可見(使用FileManager),所以安全性不是很好,雖然文檔聲稱可以在外部存儲卡上寫程序私有數(shù)據(jù),但貌似沒用,用FileManager仍然可以刪除或編輯文件(Market上面的FileManager功能都十分的強大,能讓用戶看到SD卡中的所有文件,和操作能看到的文件)。
c. Android手機支持把外部存儲卡Mount至PC做為U盤,當(dāng)連接數(shù)據(jù)線時,這時SD卡變成了U盤連接到了另外的操作系統(tǒng)中。什么意思,就是在Android當(dāng)中雖然有的文件屬性(隱藏,私有等),到了PC上就不一定管用了,用戶在PC上可以隨意操作文件(這就是第二點中所提及的)。
d. 如果使用外部存儲卡保存數(shù)據(jù),一定要額外做好異常處理:外部存儲卡不可用時把數(shù)據(jù)存入哪里;可用的時候再怎么同步數(shù)據(jù)(這是比較頭疼的地方,可行的做法就是當(dāng)SD卡不可用時不準(zhǔn)用戶寫數(shù)據(jù),但這用戶體驗又不是很好,但如你所知,很多應(yīng)用都這么干);你的數(shù)據(jù)被破壞了。當(dāng)然常見的異常也要考慮,比如空間滿了,無法寫入,磁盤壞道等。
1.SQLite Database數(shù)據(jù)庫
Android對數(shù)據(jù)庫的支持很好,它本身集成了SQLite數(shù)據(jù)庫,每個應(yīng)用都可以方便的使用它,或者更確切的說,Android完全依賴于SQLite數(shù)據(jù)庫,它所有的系統(tǒng)數(shù)據(jù)和用到的結(jié)構(gòu)化數(shù)據(jù)都存儲在數(shù)據(jù)庫中。
它具有以下優(yōu)點:
a. 效率出眾,這是無可否認(rèn)的
b. 十分適合存儲結(jié)構(gòu)化數(shù)據(jù)
c. 方便在不同的Activity,甚至不同的應(yīng)用之間傳遞數(shù)據(jù)
先前有一篇<深入理解Activity之間的數(shù)據(jù)傳遞>講到了不同Activity和不同應(yīng)用之間傳遞數(shù)據(jù)的麻煩,特別是對于大型數(shù)據(jù)結(jié)構(gòu),因為Activity雖是Java對象,但去無法像使用其他類對象那樣去創(chuàng)建一個實例然后使用它,更無法給Activity加上Setters和Getters(雖然這樣做了沒有編譯錯誤)。比較好的解決方案就是把結(jié)構(gòu)化數(shù)據(jù)寫入數(shù)據(jù)庫,然后在不同的Activity之間傳遞它們的Uri。
d. 由專門的ContentProvider來幫忙管理和維護(hù)數(shù)據(jù)庫
e. 可以方便的設(shè)置訪問權(quán)限,私有還是都可見
f. 操作方便,使用標(biāo)準(zhǔn)的CRUDE語句,ContentResolver.query(), update(), delete() insert(),詳見ContentResolver
g. 良好的可移植性和通用性,用標(biāo)準(zhǔn)的SQL語句就能實現(xiàn)CRUDE
對于它的使用方法可以去參考文檔,這里也說不清楚。
1.Internet網(wǎng)絡(luò)
網(wǎng)絡(luò)是比較不靠譜的一個,因為移動終端的網(wǎng)絡(luò)穩(wěn)定性,以及所產(chǎn)生的流量讓人傷不起,用戶更傷不起。但若是對于非常重要的實時數(shù)據(jù),或是需要發(fā)送給遠(yuǎn)端服務(wù)器處理的,也可以考慮使用網(wǎng)絡(luò)實時發(fā)送。這已經(jīng)有先例了,Apple和Google就是這樣,iPhone設(shè)備和Android設(shè)備都會在用戶不知情的情況 下收集用戶的信息,然后又在用戶不知情的情況 下發(fā)送到Apple和Google的服務(wù)器上,也就是所謂的“跟蹤門”。除此之外,智能手機(特別是Android和火熱的iPhone)上面的應(yīng)用程序都會偷偷的在后臺運行,收集用戶數(shù)據(jù),然后再偷偷的發(fā)服務(wù)器,直接傷害是用戶流量。
對比這幾種方式,可以總結(jié)下:
1. 簡單數(shù)據(jù)和配置信息,SharedPreference是首選;
2. 如果SharedPreferences不夠用,那么就創(chuàng)建一個數(shù)據(jù)庫
3. 結(jié)構(gòu)化數(shù)據(jù),一定要創(chuàng)建數(shù)據(jù)庫,雖然這稍顯煩鎖,但是好處無窮
4. 文件就是用來存儲文件(也即非配置信息或結(jié)構(gòu)化數(shù)據(jù)),如文本文件,二進(jìn)制文件,PC文件,多媒體文件,下載的文件等等。
5. 盡量不要創(chuàng)建文件
6. 如果創(chuàng)建文件,如果是私密文件或是重要文件,就存儲在內(nèi)部存儲,否則放到外部存儲
7. 不要收集用戶數(shù)據(jù),更不要發(fā)到網(wǎng)絡(luò)上,雖然你們也有很多無奈。用戶也無奈,也無辜,但更無助
平臺為開發(fā)者準(zhǔn)備了這么多的方式固然是一件好事,但我們要認(rèn)清每一種的優(yōu)點和缺點,根據(jù)實際情況選擇最合適的。還有一個原則就是最簡單原則,也就是說能用簡單的方式處理,就不要用復(fù)雜的方式。比如存儲幾個數(shù)據(jù)或簡單對象,用SharedPreference也能做到,何必還去寫個ContentProvider呢?
總體的來講,數(shù)據(jù)存儲方式有三種:一個是文件,一個是數(shù)據(jù)庫,另一個則是網(wǎng)絡(luò)。其中文件和數(shù)據(jù)庫可能用的稍多一些,文件用起來較為方便,程序可以自己定義格式;數(shù)據(jù)庫用起稍煩鎖一些,但它有它的優(yōu)點,比如在海量數(shù)據(jù)時性能優(yōu)越,有查詢功能,可以加密,可以加鎖,可以跨應(yīng)用,跨平臺等等;網(wǎng)絡(luò),則用于比較重要的事情,比如科研,勘探,航空等實時采集到的數(shù)據(jù)需要馬上通過網(wǎng)絡(luò)傳輸?shù)綌?shù)據(jù)處理中心進(jìn)行存儲并進(jìn)行處理。
對于Android平臺來講,它的存儲方式也不外乎這幾種,按方式總體來分,也是文件,數(shù)據(jù)庫和網(wǎng)絡(luò)。但從開發(fā)者的角度來講它可以分為以下五種方式:
1.SharedPreferences共享偏好
2.Internal Storage內(nèi)部存儲空間
3.External Storage外部存儲空間
4.SQLite Database數(shù)據(jù)庫
5.Internet網(wǎng)絡(luò)
這幾種方式各自有各自的優(yōu)點和缺點,要根據(jù)不同的實際情況來選擇,而無法給出統(tǒng)一的標(biāo)準(zhǔn)。下面就各種方式談?wù)勊鼈兊膬?yōu)缺點,以及最合適的使用情況:
1.Shared Preferences共享偏好
SharedPreferences是用來存儲一些Key/Value類似的成對的基本數(shù)據(jù)類型,注意,它只能存儲基本數(shù)據(jù)類型,也即int, long, boolean, String, float。事實上它完全相當(dāng)于一個HashMap,唯一不同的就是HashMap中的Value可以是任何對象,而SharedPreferences中的值只能存儲基本數(shù)據(jù)類型(primitive types)。
對于它的使用方法,可以參考Android Developer Guide,這里不重復(fù)。
如此來看,最適合SharedPreferences的地方就是保存配置信息,因為很多配置信息都是Key/Value。事實上,在Android當(dāng)中SharedPreferences使用最多的地方也是用來保存配置(Settings)信息,系統(tǒng)中的Settings中這樣,各個應(yīng)用中的Settings也是這樣。并且,Android中為了方便的使用SharedPreferences保存配置信息,它來專門有PreferenceActivity用來封裝。也就是說如果你想在應(yīng)用程序中創(chuàng)建配置(Settings),你可以直接使用PreferenceActivity和一些相關(guān)的專門為Preference封裝的組件,而不用再直接去創(chuàng)建,讀取和保存SharedPreference,F(xiàn)ramework中的這些組件會為你做這些事。
再談?wù)勔恍┦褂肧haredPreference時的技巧,它只能保存基本數(shù)據(jù)類型,但假如我想保存一個數(shù)組,怎么辦?可以把數(shù)據(jù)進(jìn)行處理,把它轉(zhuǎn)化成一個String,取出的時候再還原就好了;再如,如想保存一個對象,怎么辦,同樣,可以把對象序列化成為字符序列,或轉(zhuǎn)成String(Object.toString()),或是把它的HashCode(Object.hashCode())當(dāng)成Value保存進(jìn)去。
總之,SharedPreferences使用起來十分的方便,可以靈活應(yīng)用,因為它簡單方便,所以能用它就盡量不要用文件或是數(shù)據(jù)庫。
1.Internal Storage內(nèi)部存儲空間
所謂的內(nèi)部存儲與外部存儲,是指是否是手機內(nèi)置。手機內(nèi)置的存儲空間,稱為內(nèi)部存儲,它是手機一旦出廠就無法改變,它也是手機的硬件指標(biāo)之一,通常來講手機內(nèi)置存儲空間越大意味著手機價格會越貴(很多地方把它稱為手機內(nèi)存,但我們做軟件的知道,這并不準(zhǔn)確,內(nèi)存是指手機運行時存儲程序,數(shù)據(jù)和指令的地方;這里應(yīng)該是手機內(nèi)部存儲的簡稱為內(nèi)存,而并非嚴(yán)格意義上的內(nèi)存)。
內(nèi)部存儲空間十分有限,因而顯得可貴,所以我們要盡可能避免使用;另外,它也是系統(tǒng)本身和系統(tǒng)應(yīng)用程序主要的數(shù)據(jù)存儲所在地,一旦內(nèi)部存儲空間耗盡,手機也就無法使用了。所以對于內(nèi)部存儲空間,我們要盡量避免使用。上面所談到的Shared Preferences和下面要談到的SQLite數(shù)據(jù)庫也都是存儲在內(nèi)部存儲空間上的。
Android本身來講是一個Linux操作系統(tǒng),所以它的內(nèi)部存儲空間,對于應(yīng)用程序和用戶來講就是“/data/data"目錄。它與其他的(外部的存儲)相比有著比較穩(wěn)定,存儲方便,操作簡單,更加安全(因為可以控制訪問權(quán)限)等優(yōu)點。而它唯一的缺點就是它比較有限,比較可貴。
雖然,可以非常容易的知道程序本身的數(shù)據(jù)所在路徑,所有的應(yīng)用程序的數(shù)據(jù)路徑都是“/data/data/app-package-name/”,所有的程序用到的數(shù)據(jù),比如libs庫,SharedPreferences都是存放在這個路徑下面。但我們在使用的時候最好不要,或是千萬不要直接引用這個路徑。
使用內(nèi)部存儲主要有二個方式,一個是文件操作,一個是文件夾操作。無論哪種方式,Context中都提供了相應(yīng)的函數(shù)來支持,使用Context不但操作簡單方便,最重要的是Context會幫助我們管理這些文件,也可以方便幫助我們控制文件的訪問權(quán)限。先來系統(tǒng)的說下Context中關(guān)于文件和文件夾操作的函數(shù)有哪些。
a. 創(chuàng)建一個文件,并打開成一個文件輸出流,需要提供一個String,作為文件名
復(fù)制代碼 代碼如下:
FileOutputStream output = Context.openOutputFile(filename, Context.MODE_PRIVATE);
output.write(data);// use output to write whatever you like
output.close();
b. 同樣,想打開一個文件作為輸入的話,也是只需要提供文件名
復(fù)制代碼 代碼如下:
FileInputStream input = Context.openInputFile(filename);
input.read();
input.close();
c. 列出所有的已創(chuàng)建的文件
復(fù)制代碼 代碼如下:
String[] files = Context.fileList();
for (String file : files) {
Log.e(TAG, "file is " + file);
}
d. 刪除文件,能創(chuàng)建就要能夠刪除,當(dāng)然也會提供了刪除文件的接口,它也非常簡單,只需要提供文件名
復(fù)制代碼 代碼如下:
if (Context.deleteFile(filename)) {
Log.e(TAG, "delete file " + filename + " sucessfully“);
} else {
Log.e(TAG, "failed to delete file " + filename);
}
e. 獲取文件已創(chuàng)建文件的路徑,它返回一個文件對象用于操作路徑
復(fù)制代碼 代碼如下:
File fileDir = Context.getFileDir();
Log.e(TAG, "fileDir " + fileDir.getAbsolutePath();
f. 創(chuàng)建一個目錄,需要傳入目錄名稱,它返回 一個文件對象用到操作路徑
復(fù)制代碼 代碼如下:
File workDir = Context.getDir(dirName, Context.MODE_PRIVATE);
Log.e(TAG, "workdir " + workDir.getAbsolutePath();
g. 以File對象方式查看所創(chuàng)建文件,需要傳入文件名,會返回文件對象
復(fù)制代碼 代碼如下:
File store = Context.openFileStreamPath(filename);
Log.e(TAG, "store " + store.length());
h. 獲取Cache路徑,無需要傳入?yún)?shù),返回文件對象
復(fù)制代碼 代碼如下:
File cachedir = Context.getCacheDir();
Log.e(TAG, "cachedir " + cacheDir.getAbsolutePath());
總結(jié)一下文件相關(guān)操作,可以得出以下三個特點:
1. 文件操作只需要向函數(shù)提供文件名,所以程序自己只需要維護(hù)文件名即可;
2. 不用自己去創(chuàng)建文件對象和輸入、輸出流,提供文件名就可以返回File對象或輸入輸出流
3. 對于路徑操作返回的都是文件對象。
如前所述,內(nèi)部存儲空間有限,可貴,安全,穩(wěn)定,所以應(yīng)該用來保存比較重要的數(shù)據(jù),比如用戶信息資料,口令秘碼等不需要與其他應(yīng)用程序共享的數(shù)據(jù)。也可以用來創(chuàng)建臨時文件,但一定要注意及時刪除。另外,對于內(nèi)部存儲還有一個非常重要的特點,那就是在應(yīng)用程序被卸載時,應(yīng)用程序在內(nèi)部存儲空間的文件數(shù)據(jù)將全部被刪除。系統(tǒng)這樣做的原因很簡單,就是因為內(nèi)部存儲很有限,它必須保證它的可用性,因為一旦添滿,系統(tǒng)將無法再正常工作。
1.External Storage外部存儲空間
再來談?wù)勈謾C外部存儲空間,與內(nèi)部存儲空間相對,外部存儲空間是指手機出廠的時候不存在,用戶在使用時候可以自由添加的外部存儲介質(zhì)比如TS卡,SD卡等閃存儲介質(zhì)。這些閃存介質(zhì)由最初的空間小價格貴,到現(xiàn)在的大容量價格便宜,所以幾乎每個支持外部存儲的手機上面都有大容量(大于等于2G)的閃存卡。
Android也是不例外,它完全支持外部存儲介質(zhì)。其實更確切的說,它是要依賴于外部存儲卡的,因為對于Android系統(tǒng),如果沒有外部存儲卡,很多的系統(tǒng)應(yīng)用無法使用,比如多媒體相關(guān)的應(yīng)用程序無法使用。雖然Android很依賴,但是外部存儲卡也有它自身的特點,它最大的優(yōu)點就是存儲空間大,基本上你可無限制的使用,也不怎么擔(dān)心去清除數(shù)據(jù)。就目前來看,很多程序都在使用外部存儲卡,但很少有程序去主動清理數(shù)據(jù),所以無論你的SD卡有多大,它的可用空間卻越來越少。與內(nèi)部存儲不同的是,當(dāng)程序卸載時,它在外部存儲所創(chuàng)建的文件數(shù)據(jù)是不會被清除的。所以清理外部存儲空間的責(zé)任丟給了用戶自己,每隔一段時間就去查看下SD卡,發(fā)現(xiàn)無用數(shù)據(jù)立馬刪除。外部存儲的缺點就是不是很穩(wěn)定,對于Android手機來講可以說,很不穩(wěn)定,本身閃存介質(zhì)就容易出問題,SD卡處于不能正常使用的狀態(tài)十分多。
先來說說外部存儲相關(guān)的使用方法和API:
a. Check media availability檢查介質(zhì)的可用性
如前所述,外部存儲介質(zhì)的穩(wěn)定性十分的差,所以在使用之前一定要先檢查它的可用性,如果可用再去用
復(fù)制代碼 代碼如下:
final String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED) || state.equals(Environment.MEDIA_READ_ONLY)) {// sd card is ready to us }
b. Get the directory獲取外部存儲卡的路徑
事實上,外部存儲卡的路徑是“/mnt/sdcard",所以你直接這樣寫去訪問也能訪問的到。鑒于可讀性和可移植性的考慮,建議這樣寫:
復(fù)制代碼 代碼如下:
File sdcardDir = Environment.getExternalStorageDirectory();
c. For API 8 or greater, there are some other useful APIs helping to manager files and directories.
如果你使用API 8(Android 2.2)或者更高,那么SDK中又多了幾個操作外部存儲文件和路徑的接口,文檔中也建議開始者更加規(guī)范的使用SD卡。比如,創(chuàng)建相應(yīng)的目錄去存儲相應(yīng)的數(shù)據(jù),Music,Picture,Video等。應(yīng)用程序目錄也變成了"/Android/data/package-name/data"。具體的使用可以參考文檔,這里不重復(fù)。當(dāng)然,就像編程規(guī)范一樣,這里只是規(guī)范,你完全可以不遵守它,但出于可讀性和可移植性,還是建議按照文檔建議的去做。
下面總結(jié)一下使用時應(yīng)該注意的一些和外部存儲的特點:
a. 外部存儲卡不是隨時想用就能夠用的,所以一定要記得在使用之前檢查它的可用性
b. 存儲在外部存儲卡上的數(shù)據(jù)是所有應(yīng)用程序都可見,用戶也可見(使用FileManager),所以安全性不是很好,雖然文檔聲稱可以在外部存儲卡上寫程序私有數(shù)據(jù),但貌似沒用,用FileManager仍然可以刪除或編輯文件(Market上面的FileManager功能都十分的強大,能讓用戶看到SD卡中的所有文件,和操作能看到的文件)。
c. Android手機支持把外部存儲卡Mount至PC做為U盤,當(dāng)連接數(shù)據(jù)線時,這時SD卡變成了U盤連接到了另外的操作系統(tǒng)中。什么意思,就是在Android當(dāng)中雖然有的文件屬性(隱藏,私有等),到了PC上就不一定管用了,用戶在PC上可以隨意操作文件(這就是第二點中所提及的)。
d. 如果使用外部存儲卡保存數(shù)據(jù),一定要額外做好異常處理:外部存儲卡不可用時把數(shù)據(jù)存入哪里;可用的時候再怎么同步數(shù)據(jù)(這是比較頭疼的地方,可行的做法就是當(dāng)SD卡不可用時不準(zhǔn)用戶寫數(shù)據(jù),但這用戶體驗又不是很好,但如你所知,很多應(yīng)用都這么干);你的數(shù)據(jù)被破壞了。當(dāng)然常見的異常也要考慮,比如空間滿了,無法寫入,磁盤壞道等。
1.SQLite Database數(shù)據(jù)庫
Android對數(shù)據(jù)庫的支持很好,它本身集成了SQLite數(shù)據(jù)庫,每個應(yīng)用都可以方便的使用它,或者更確切的說,Android完全依賴于SQLite數(shù)據(jù)庫,它所有的系統(tǒng)數(shù)據(jù)和用到的結(jié)構(gòu)化數(shù)據(jù)都存儲在數(shù)據(jù)庫中。
它具有以下優(yōu)點:
a. 效率出眾,這是無可否認(rèn)的
b. 十分適合存儲結(jié)構(gòu)化數(shù)據(jù)
c. 方便在不同的Activity,甚至不同的應(yīng)用之間傳遞數(shù)據(jù)
先前有一篇<深入理解Activity之間的數(shù)據(jù)傳遞>講到了不同Activity和不同應(yīng)用之間傳遞數(shù)據(jù)的麻煩,特別是對于大型數(shù)據(jù)結(jié)構(gòu),因為Activity雖是Java對象,但去無法像使用其他類對象那樣去創(chuàng)建一個實例然后使用它,更無法給Activity加上Setters和Getters(雖然這樣做了沒有編譯錯誤)。比較好的解決方案就是把結(jié)構(gòu)化數(shù)據(jù)寫入數(shù)據(jù)庫,然后在不同的Activity之間傳遞它們的Uri。
d. 由專門的ContentProvider來幫忙管理和維護(hù)數(shù)據(jù)庫
e. 可以方便的設(shè)置訪問權(quán)限,私有還是都可見
f. 操作方便,使用標(biāo)準(zhǔn)的CRUDE語句,ContentResolver.query(), update(), delete() insert(),詳見ContentResolver
g. 良好的可移植性和通用性,用標(biāo)準(zhǔn)的SQL語句就能實現(xiàn)CRUDE
對于它的使用方法可以去參考文檔,這里也說不清楚。
1.Internet網(wǎng)絡(luò)
網(wǎng)絡(luò)是比較不靠譜的一個,因為移動終端的網(wǎng)絡(luò)穩(wěn)定性,以及所產(chǎn)生的流量讓人傷不起,用戶更傷不起。但若是對于非常重要的實時數(shù)據(jù),或是需要發(fā)送給遠(yuǎn)端服務(wù)器處理的,也可以考慮使用網(wǎng)絡(luò)實時發(fā)送。這已經(jīng)有先例了,Apple和Google就是這樣,iPhone設(shè)備和Android設(shè)備都會在用戶不知情的情況 下收集用戶的信息,然后又在用戶不知情的情況 下發(fā)送到Apple和Google的服務(wù)器上,也就是所謂的“跟蹤門”。除此之外,智能手機(特別是Android和火熱的iPhone)上面的應(yīng)用程序都會偷偷的在后臺運行,收集用戶數(shù)據(jù),然后再偷偷的發(fā)服務(wù)器,直接傷害是用戶流量。
對比這幾種方式,可以總結(jié)下:
1. 簡單數(shù)據(jù)和配置信息,SharedPreference是首選;
2. 如果SharedPreferences不夠用,那么就創(chuàng)建一個數(shù)據(jù)庫
3. 結(jié)構(gòu)化數(shù)據(jù),一定要創(chuàng)建數(shù)據(jù)庫,雖然這稍顯煩鎖,但是好處無窮
4. 文件就是用來存儲文件(也即非配置信息或結(jié)構(gòu)化數(shù)據(jù)),如文本文件,二進(jìn)制文件,PC文件,多媒體文件,下載的文件等等。
5. 盡量不要創(chuàng)建文件
6. 如果創(chuàng)建文件,如果是私密文件或是重要文件,就存儲在內(nèi)部存儲,否則放到外部存儲
7. 不要收集用戶數(shù)據(jù),更不要發(fā)到網(wǎng)絡(luò)上,雖然你們也有很多無奈。用戶也無奈,也無辜,但更無助
平臺為開發(fā)者準(zhǔn)備了這么多的方式固然是一件好事,但我們要認(rèn)清每一種的優(yōu)點和缺點,根據(jù)實際情況選擇最合適的。還有一個原則就是最簡單原則,也就是說能用簡單的方式處理,就不要用復(fù)雜的方式。比如存儲幾個數(shù)據(jù)或簡單對象,用SharedPreference也能做到,何必還去寫個ContentProvider呢?
您可能感興趣的文章:
- Android應(yīng)用開發(fā)SharedPreferences存儲數(shù)據(jù)的使用方法
- android中使用SharedPreferences進(jìn)行數(shù)據(jù)存儲的操作方法
- Android調(diào)用相機并將照片存儲到sd卡上實現(xiàn)方法
- Android編程實現(xiàn)手機自帶內(nèi)部存儲路徑的獲取方法
- Android APP與媒體存儲服務(wù)的交互
- Android App將數(shù)據(jù)寫入內(nèi)部存儲和外部存儲的示例
- Android 數(shù)據(jù)存儲方式有哪幾種
- 在android開發(fā)中進(jìn)行數(shù)據(jù)存儲與訪問的多種方式介紹
- Android編程中的5種數(shù)據(jù)存儲方式
- Android學(xué)習(xí)之SharedPerference存儲詳解
相關(guān)文章
Android短信接收監(jiān)聽、自動回復(fù)短信操作例子
本文實現(xiàn)了短信接收監(jiān)聽,當(dāng)接收到短信時,可自動回復(fù)短信,或自動回?fù)茈娫?,同時監(jiān)聽短信的發(fā)送狀態(tài)2014-04-04Android?flutter?Dio鎖的巧妙實現(xiàn)方法示例
這篇文章主要為大家介紹了Android?flutter?Dio鎖的巧妙實現(xiàn)方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01開源電商app常用標(biāo)簽"hot"之第三方開源LabelView
這篇文章主要介紹了開源電商app常用標(biāo)簽"hot"之第三方開源LabelView,對開源電商app相關(guān)資料感興趣的朋友一起學(xué)習(xí)吧2015-12-12Android 使用 Path 實現(xiàn)搜索動態(tài)加載動畫效果
這篇文章主要介紹了Android 使用 Path 實現(xiàn)搜索動態(tài)加載動畫效果,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2018-08-08