Android數(shù)據(jù)存儲方式File
Internal Storage VS External Storage
在使用File存儲App數(shù)據(jù)時,我們需要了解Android系統(tǒng)的存儲系統(tǒng)。Android的存儲分為內(nèi)部存儲和外部存儲。
所有的Android設(shè)備都有兩塊存儲區(qū)域:Internal Storage和External Storage。它們的名稱來源于早期的Android系統(tǒng),那時候大家的手機都內(nèi)置(Permanent)一塊較小存儲板(即Internal Storage),并配上一個的外置的(Removable)儲存卡(即External Storage)。后來部分手機開始將最初定義的“Internal Storage”,即內(nèi)置存儲,分成Internal和External兩部分。這樣一來就算沒有外置儲存,手機也有Internal和External兩塊存儲區(qū)域。(引用自博文,Android存儲挖坑記)
Internal Storage
- /data/data/package name/files
- /data/data/package name/cache
- /data/data/package name/databases
- /data/data/package name/shared_prefs

External Storage
由于Android系統(tǒng)的廠商比較多,對于外部存儲目錄的定義有所不同,可能在根目錄下的mnt,sdcard和storage下。以storage為例,打開emulated/0目錄,外部存儲目錄就出現(xiàn)了。雖然可以通過多種路徑打開外部存儲文件,但是最終他們的路徑是相同的:

mnt:

storage:

sdcard:

外部存儲目錄下包含兩大類:公有目錄和私有目錄
- 公有目錄:包括九大系統(tǒng)創(chuàng)建的文件夾:Download,DICM之類的
- 私有目錄:路徑為/Android/data/package name/。這里包含了上述的九大文件和cache文件。
私有目錄:

| 對比項 | Internal Storage | External Storage |
|---|---|---|
| 可信度 | 永遠(yuǎn)可用(Permanent) | 可能不可用,最典型的當(dāng)設(shè)備作為USB存儲被mount時不可用 |
| 訪問權(quán)限 | App存儲內(nèi)容僅App本身(或共享uid的App)可訪問(Root除外) | App存儲內(nèi)容全局可讀 |
| 內(nèi)容持久 | App存儲內(nèi)容隨App卸載而消失 | 當(dāng)App卸載時,只有存在Android/data/package name/路徑下的文件會消失 |
| 適用情況 | 存儲內(nèi)容僅App自己訪問時的最佳選擇 | 存儲內(nèi)容希望與其他App共享或傳到電腦上,但是不想申請任何權(quán)限時的最佳選擇 |
引用自博文,Android存儲挖坑記
對比下來External有以下幾點優(yōu)點:
- 通過USB可以將數(shù)據(jù)傳到電腦上
- 可以與其他App共享數(shù)據(jù)
- 在Android/data/package name/路徑以外的數(shù)據(jù)不會因為程序卸載而被刪除
缺點:
- 外置存儲有時不可用
- 在非root情況下,數(shù)據(jù)無法私有化
- 在Android/data/package name/路徑以外存儲數(shù)據(jù)需要申請寫入權(quán)限
存儲權(quán)限申請
內(nèi)部存儲與外部存儲權(quán)限申請對比如下:
| Android版本 | Internal Storage | External Storage |
|---|---|---|
| 4.4以下 | 無需權(quán)限 | 需要申請WRITE_EXTERNAL_STORAGE |
| 4.4及以上 | 無需權(quán)限 | 除了Android/data/package name/目錄下,都需要申請WRITE_EXTERNAL_STORAGE |
注意:目前,所有App都可以讀External存儲而不需要任何權(quán)限,這一點可能會在未來做出改變。如果你希望讀External存儲,那最好申請一下READ_EXTERNAL_STORAGE權(quán)限。另外,寫權(quán)限已經(jīng)默認(rèn)包含了讀權(quán)限了。
Internal Storage存儲數(shù)據(jù)
- Android數(shù)據(jù)存儲之File方法getFilesDir()和openFileOutput(String name)返回的路徑相同
- Android數(shù)據(jù)存儲之SharedPreferences
- Databases
- Content Provider
External Storage存儲數(shù)據(jù)
首先我們要獲取外部存儲目標(biāo)文件的路徑:
| 目標(biāo)目錄 | 獲取方法 |
|---|---|
| 公有目錄九大文件 | Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) |
| 公有根目錄 | Environment.getExternalStorageDirectory() |
| 私有目錄file | Context.getExternalFilesDir(Environment.DIRECTORY_MUSIC) |
| 私有目錄cache | Context.getExternalCacheDir() |
然后確定自己需要創(chuàng)建的文件名,結(jié)合上面的到的路徑,創(chuàng)建一個File對象:
private void saveExternal(String str) {
FileOutputStream outputStream = null;
DataOutputStream out = null;
try{
try{
outputStream = new FileOutputStream(
new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS),
"data_external.dat"));
out = new DataOutputStream(new BufferedOutputStream(outputStream));
out.writeUTF(str);
}finally {
out.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
上述表格中的方法,有兩個方法需要傳入一個String類型的參數(shù),這個參數(shù)我們使用了Environment中的常量,參數(shù)的意思是我們要訪問這個路徑下的哪個文件夾。
App數(shù)據(jù)清理
Android系統(tǒng)默認(rèn)數(shù)據(jù)清理的路徑是,內(nèi)部存儲目錄中相應(yīng)的cache文件夾中的文件和外部存儲中相應(yīng)的cache文件夾中的文件。
細(xì)節(jié)
內(nèi)部存儲
你的app的internal storage 目錄是以你的app的包名作為標(biāo)識存放在Android文件系統(tǒng)的特定目錄下[data/data/com.example.xx]。 從技術(shù)上講,如果你設(shè)置文件為可讀的,那么其他app就可以讀取你的internal文件。然而,其他app需要知道你的包名與文件名。若是你沒有設(shè)置為可讀或者可寫,其他app是沒有辦法讀寫的。因此只要你使用MODE_PRIVATE ,那么這些文件就不可能被其他app所訪問。
另外記住一點,內(nèi)部存儲在你的APP卸載的時候,會一塊被刪除,因此,我們可以在cache目錄里面放置我們的圖片緩存,而且cache與files的差別在于,如果手機的內(nèi)部存儲空間不夠了,會自行選擇cache目錄進行刪除,因此,不要把重要的文件放在cache文件里面,可以放置在files里面,因為這個文件只有在APP被卸載的時候才會被刪除。還有要注意的一點是,如果應(yīng)用程序是更新操作,內(nèi)部存儲不會被刪除,區(qū)別于被用戶手動卸載。
外部存儲
不管你是使用 getExternalStoragePublicDirectory() 來存儲可以共享的文件,還是使用 getExternalFilesDir() 來儲存那些對于你的app來說是私有的文件,有一點很重要,那就是你要使用那些類似DIRECTORY_PICTURES 的API的常量。那些目錄類型參數(shù)可以確保那些文件被系統(tǒng)正確的對待。例如,那些以DIRECTORY_RINGTONES 類型保存的文件就會被系統(tǒng)的media scanner認(rèn)為是ringtone而不是音樂。
清除數(shù)據(jù)、清除緩存的區(qū)別
- 清除數(shù)據(jù)主要是清除用戶配置,比如SharedPreferences、數(shù)據(jù)庫等等,這些數(shù)據(jù)都是在程序運行過程中保存的用戶配置信息,清除數(shù)據(jù)后,下次進入程序就和第一次進入程序時一樣
- 緩存是程序運行時的臨時存儲空間,它可以存放從網(wǎng)絡(luò)下載的臨時圖片,從用戶的角度出發(fā)清除緩存對用戶并沒有太大的影響,但是清除緩存后用戶再次使用該APP時,由于本地緩存已經(jīng)被清理,所有的數(shù)據(jù)需要重新從網(wǎng)絡(luò)上獲取。為了在清除緩存的時候能夠正常清除與應(yīng)用相關(guān)的緩存,請將緩存文件存放在getCacheDir()或者 getExternalCacheDir()路徑下。
總結(jié)
在開發(fā)中,不建議往內(nèi)部存儲中寫太多的數(shù)據(jù),畢竟空間有限。外部存儲在使用的時候最好能夠?qū)⑽募娣旁谒接心夸浵?,這樣有利于系統(tǒng)維護,也避免用戶的反感。