1 概念總述linux
android開發中,關於存儲路徑,咱們常常聽到如下幾個概念:內存、內部存儲和外部存儲,如今咱們就來詳細說說這三者區別與聯繫。android
內存:英文中記爲memory,即RAM數據庫
內部存儲:英文記爲InternalStorage,即內部ROMapi
外部存儲:英文記爲ExternalStorage, 即外部ROM和SDCard緩存
由上可知三者在英文中不會產生太大的歧義,可是當咱們翻譯爲中文後,對於三者之間的關係就開始模糊化了。最容易混淆的是外部存儲,咱們廣泛認爲機身固有的存儲是內部存儲,而擴展的T卡是外部存儲。早期的android設備內部存儲確實是固定的,而外部存儲確實是能夠像U盤同樣移動的。可是在後來的設備中,不少中高端的機器都將本身的機身存儲擴展到了8G以上,他們將存儲在概念上分紅了"內部internal"和"外部external"兩部分,但其實都在手機內部。因此無論android手機是否有可移動的sdcard,他們老是有外部存儲和內部存儲。最關鍵的是,咱們都是經過相同的api來訪問可移動的sdcard或者手機自帶的存儲。微信
Android 內存app
手機的整個存儲空間分爲內部存儲和外部存儲兩部分,內部存儲中又包含RAM和ROM等部分。函數
內部存儲,即InternalStorage,也常說內置存儲卡,這是手機內置的存儲空間,出廠時就被肯定,是手機的一個硬件指標。類比電腦的內存。測試
外部存儲,即ExternalStorage,也常說外置存儲卡,手機出廠時並不存在,是由用戶自由擴展的存儲空間,常見的就是SD卡。類比電腦的外接移動硬盤。
RAM,即常說的運行時內存,是手機運行時存儲數據和指令的地方,注意是運行時內存。類比電腦的內存條。spa
ROM,用來存放一些系統文件,應用配置和其餘數據的地方,是內部存儲中主要存儲區域。類比於Windows電腦的C盤。
在 Android Studio 使用 DDMS 的 File Exploer 窗口中查看文件系統,下圖就是一個 Android 文件系統目錄。
Android 文件系統目錄
這裏有三個文件夾須要注意,data、mnt和storage,data是指內部存儲,mnt和storage指外部存儲。下面將詳細介紹內部存儲和外部存儲。
2 內部存儲
內部存儲位於系統中很特殊的一個位置,若是你想將文件存儲於內部存儲中,那麼文件默認只能被你的應用訪問到,且一個應用建立的全部文件都在和應用包名相同的目錄下。當一個應用卸載後,內部存儲中的這些文件也被刪除。內部存儲空間十分有限,它是系統自己和系統應用程序主要的數據存儲所在地,一旦內部存儲空間耗盡,手機就沒法使用了。Shared Preferences和SQLite數據庫都是存儲在內部存儲空間上的。內部存儲通常用Context來獲取和操做。內部存儲有兩個重要目錄:
1)app文件夾:沒有root的手機不能打開該文件夾。app文件夾裏存放着系統中安裝的第三方應用的apk文件,當咱們調試一個app的時候,能夠看到控制檯輸出的內容,有一項是uploading...,就是上傳咱們的apk到這個文件夾,上傳成功後纔開始安裝。
2)data文件夾:
該文件夾存放存儲包私有數據,對於設備中每個安裝的 App,系統都會在內部存儲空間的 data/data 目錄下以應用包名爲名字自動建立與之對應的文件夾。
用戶卸載 App 時,系統自動刪除 data/data 目錄下對應包名的文件夾及其內容。
該目錄下又把存儲內容進行了分類:
3)路徑獲取API
/data Environment.getDataDirectory();
/data/data/包名/files context.getFilesDir();
//對於 Files 目錄下的文件,一般不會經過 File 類的方式直接進行讀寫,而是利用一些封裝過的類或函數進行操做: public FileInputStream openFileInput(String name) public FileOutputStream openFileOutput(String name, int mode)
//還能夠直接刪除或查詢該目錄下的文件: context.deleteFile(name) context.fileList()
/data/data/包名/cache context.getCacheDir();
/data/data/包名/shared_prefs context.getSharedPreferences(name,mode)//返回的是 SharedPreferences 對象 context.deleteSharedPreferences(name)
/data/data/包名/databases context.getDataDir() context.getDatabasePath(name) context.deleteDatabase(name)
/data/data/包名/app_name context.getDir(name,mode) //經測試該方法會在 /data/data/包名/ 目錄下生成一個以 app_ 開頭的目錄
3 外部存儲
每一個兼容 Android 的設備都支持可用於保存文件的共享「外部存儲」。 該存儲多是可移除的存儲介質(例如 SD 卡)或內部(不可移除)存儲。 保存到外部存儲的文件是全局可讀取文件,並且,在計算機上啓用 USB 大容量存儲以傳輸文件後,可由用戶修改這些文件。
Environment.getExternalStorageState()
返回值爲如下幾種:
MEDIA_MOUNTED:sd卡正常掛載
MEDIA_REMOVED:無介質
MEDIA_UNMOUNTED:有介質,未掛載,在系統中刪除
MEDIA_BAD_REMOVAL:介質在掛在前被移除,直接取出sd卡。
MEDIA_CHECKING:正在磁盤檢查,剛裝上sd卡時
MEDIA_SHARED:sd卡存在但沒有掛載,而且經過USB大容量存儲共享,操做打開USB存儲
MEDIA_MOUNTED_READ_ONLY:sd卡存在而且已掛載,可是掛載方式爲只讀
MEDIA_NOFS:介質存在可是爲空白,或用在不支持的文件系統
MEDIA_UNMOUNTABLE:存在sd卡可是不能掛載,例如發生介質損壞
掛載:這是linux系統的術語,就是加載的意思,把sd卡劃入系統相連,讓系統能認到並讀取sd卡的內容。
當sd卡狀態爲MEDIA_MOUNTED時,/mnt/sdcard目錄纔是可讀可寫,而且能夠建立目錄及文件。其餘狀況一概不可讀可寫。
讀取sd卡通常會這麼寫。
String state; String path; state = Environment.getExternalStorageState(); if(state.equals(Environment.MEDIA_MOUNTED)){ path = Environment.getExternalStorageDirectory().getAbsolutePath(); }
讀寫sd卡不要忘了權限問題,需加入如下兩個權限
* 1 在AndroidManifest文件中加入sdcard操做權限 <!--在SDCard中建立與刪除文件權限 --> <uses-permissioandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!--往SDCard寫入數據權限 --> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/> * 2 確認sdcard的存在 android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED) * 3 獲取擴展存儲設備的文件目錄 android.os.Environment.getExternalStorageDirectory();
Android 在外部存儲上提供了十個公共目錄來存儲相對應的文件:
經過 API Environment.getExternalStoragePublicDirectory(type)
來訪問
/storage/emulated/0/Music
/storage/emulated/0/Podcasts
/storage/emulated/0/Ringtones
/storage/emulated/0/Alarms
/storage/emulated/0/Notifications
/storage/emulated/0/Pictures
/storage/emulated/0/Movies
/storage/emulated/0/Downloads
/storage/emulated/0/Dcim
/storage/emulated/0/Documents
3)私有目錄
Android2.2 引入了基於擴展存儲器的應用緩存目錄,該目錄指向大容量的擴展存儲器。與應用的內存私有目錄同樣,緩存目錄會隨着應用的卸載一併刪除。
和內部存儲同樣,會在 SD 卡的 Android/data 目錄下生成對應包名的文件夾
/storage/emulated/0/Android/data/應用包名/files context.getExternalFilesDir(type)
/storage/emulated/0/Android/data/應用包名/cache context.getExternalCacheDir()
在 Android 目錄下除了 data 目錄還有一個 obb 目錄 /storage/emulated/0/Android/obb/應用包名 context.getObbDir()
4)其餘目錄
Environment.getDownloadCacheDirectory()
訪問,存儲下載文件的緩存路徑Environment.getRootDirectory()
訪問,該目錄下也有一個 app 目錄,存放的是系統應用的 apk 文件。/mnt 目錄
這個目錄專門用來看成掛載點掛在外部設備的,如 SD 卡,sdcard
將會被系統視做一個文件夾,這個文件夾將會被系統嵌入到收集系統的 mnt 目錄中,因此在 /mnt 目錄下也會看到一個 sdcard 的快捷方式:
4 總結
A: getCacheDir(): 獲取/data/data//cache目錄
getFileDir(): 獲取/data/data/files目錄
這兩個目錄中的內容必須是root的手機在文件操做系統中才能看到。固然若是在應用程序中清空數據或者卸載應用,那麼這兩個目錄下的文件也將會被清空的。
B: getExternalFilesDir(): 獲取SDCard/Android/data/你的應用的包名/files/目錄(通常存放一些長時間保存的數據)
getExternalCacheDir(): 獲取SDCard/Android/data/你的應用包名/cache/目錄(通常存放臨時緩存的數據)
這兩個是放在外置存儲卡的,這個目錄下的內容,可使用文件瀏覽系統查看到,可是若是清空數據或者卸載應用,這兩個目錄下的文件也將被清空。
當應用被用戶卸載後,SDCard/Android/data/你的應用包名/這個目錄下的全部文件都會被刪除,不會留下垃圾信息。A、B兩種方式的緩存都會在卸載app的時候被系統清理到,而開發者本身在sd卡上創建的緩存文件夾,是不會隨着app的卸載而被清除掉的。
getCacheDir:/data/data/com.example.sinatext/cache getFilesDir:/data/data/com.example.sinatext/files getExternalCacheDir:/storage/sdcard0/Android/data/com.example.sinatext/cache getExternalFilesDir:/storage/sdcard0/Android/data/com.example.sinatext/files/text getDatabasePath:/data/data/com.example.sinatext/databases/text getDir:/data/data/com.example.sinatext/app_modeDir getPackageResourcePath:/data/app/com.example.sinatext-2.apk Environment.getDataDirectory():/data Environment.getExternalStorageState():mounted Environment.getDownloadCacheDirectory():/cache Environment.getExternalStorageDirectory():/storage/sdcard0 Environment.getRootDirectory():/system
按照路徑的特徵,咱們又能夠將文件存儲的路徑分爲兩大類,一類是路徑中含有包名的,一類是路徑中不含有包名的,含有包名的路徑,由於和某個App有關,因此對這些文件夾的訪問都是調用Context裏邊的方法,而不含有包名的路徑,和某一個App無關,咱們能夠經過Environment中的方法來訪問。
清除數據:相似於恢復出廠設置,刪除了全部用戶保存的數據。則是指一些固定的用戶信息,好比登陸信息、進度保存信息等,清理以後,再次運行對應的App,好比微信,則須要從新輸入登陸信息,而若是是遊戲,特別是單機遊戲,則就像新遊戲同樣,以前的進度信息都會被清除而沒法繼續。即將外部私有數據包(/storage/emulated/0/Android/data/包名)清除,將內部數據下的全部內容(/data/data/包名/XXX)清除;
清除緩存:只是刪除了應用軟件的緩存資源。手機App應用在運行過程當中會產生一些臨時數據,好比加載過的頁面、填寫過的數據等,這些數據的存在有利於對應App無需屢次加載而運行加快,這些數據稱之爲「緩存數據「。清理緩存表示將這些臨時數據清除,清除後,對應App再次運行須要從新生成,可能會變慢,可是總體手機運行內存因其釋放而增長,反而可能加快。即將外部私有數據下的cache包(/storage/emulated/0/Android/data/包名/cache)清除,將內部數據下的cache包下的內容(/data/data/包名/cache/XXX)清除 。
參考博文http://blog.csdn.net/summerinnphuket/article/details/50790365https://www.jianshu.com/p/80e10b3dbba5