Android開發過程中,我們經常會需要儲存檔案,所以我們也應該整理一下這方面的相關知識,維護好使用者裝置的檔案,更需要知道內部儲存和外部儲存的區別。
本文思維導圖
先來看一下我們本章節的思維導圖,希望能夠幫助你用碎片化或者儘量短的時間,直白、深刻的瞭解本文的知識點。
內部儲存
是否需要使用者許可權:否
是否能被其他應用訪問:否
解除安裝應用資料是否被刪除:是
內部儲存控制元件不需要使用者許可權,這意味著我們不需要使用者去授權android.permission.WRITE_EXTERNAL_STORAGE
和android.permission.READ_EXTERNAL_STORAGE
我們就可以讀寫該目錄下的檔案。而且該目錄下的檔案不能被其他應用訪問。這也就保證了我們應用內部儲存的檔案的安全性和隱私性,如果我們需要檢視自己應用內部的檔案,我們可以通過Android Studio的Device File Explore工具進行訪問:
我們可以訪問/data/data/應用包名,檢視自己應用下的內部儲存檔案。
/data/data/應用名/cache :存放的是APP的快取資訊
/data/data/應用名/code_cache :在執行時存放應用產生的編譯或者優化的程式碼
/data/data/應用名/files : 存放APP的檔案資訊
還有一些執行時,產生的資料夾,例如呼叫SharedPreference所產生的 /data/data/應用包名/shared_prefs 目錄,存放著app的SharedPreference所產生的xml檔案,還有呼叫資料庫所產生的 **/data/data/應用包名/databases/**資料夾,這裡就不一一舉例。
相關API
getCacheDir
File getCacheDir() 返回內部儲存的cache資料夾
Log.d("DaMai",getCacheDir().getPath()); //data/user/0/com.example.vicky.yinji/cache
複製程式碼
getCodeCacheDir
File getCodeCacheDir() 返回內部儲存的code_cache資料夾,要求Android5.0+
Log.d("DaMai",getCodeCacheDir().getPath()); ///data/user/0/com.example.vicky.yinji/code_cache
複製程式碼
getFilesDir
File getFilesDir() 訪問內部儲存的files目錄
Log.d("DaMai",getFilesDir().getPath()); ///data/user/0/com.example.vicky.yinji/files
複製程式碼
fileList
String[] fileList() 返回files目錄下的檔名,例如files目錄下有test.txt檔案和test1.txt檔案
//輸出 test.txt和test1.txt
for (String item : fileList()){
Log.d("DaMai",item);
}
複製程式碼
openFileOutput
FileOutputStream openFileOutput() 寫檔案到files目錄下:
try {
FileOutputStream outputStream = openFileOutput("test.txt", Context.MODE_PRIVATE);
outputStream.write("this is test content".getBytes());
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
複製程式碼
此時file目錄下就會多了一個test.txt檔案
openFileInput
FileInputStream openFileInput() 讀files目錄下檔案,例如我們讀剛剛寫入的test.txt檔案
// 輸出:this is test content
try {
FileInputStream fileInputStream = openFileInput("test.txt");
byte[] bytes = new byte[1024];
StringBuffer stringBuffer = new StringBuffer();
int len = 0;
while ((len=fileInputStream.read(bytes))!=-1){
stringBuffer.append(new String(bytes,0,len));
}
Log.d("DaMai",stringBuffer.toString());
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
複製程式碼
getDataDir
File getDataDir() 返回內部儲存的根資料夾,要求Android7.0+
Log.d("DaMai",getDataDir().getPath()); ///data/user/0/com.example.vicky.yinji
複製程式碼
外部儲存
公共目錄
是否需要使用者許可權:是
是否能被其他應用訪問:是
解除安裝應用資料是否被刪除:否
公共目錄必須需要使用者授權讀寫的許可權,這意味著我們需要在AndroidManifest.xml
中註冊使用者許可權。
<!-- 往SDCard寫入資料許可權 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
複製程式碼
並且在Android 6.0系統之後需要申請使用者許可權,並獲得使用者授權,才能讀寫檔案。
公共目錄相對開放,我們可以訪問其他APP存在公共目錄下的檔案,並且當APP被刪除時,並不會刪除應用存在公共目錄下的檔案。
我們可以通過Environment物件,訪問讀寫公共目錄的檔案。接下來讓我們看看相關的API。
相關API
Environment.getExternalStorageDirectory
File Environment.getExternalStorageDirectory() 訪問外部儲存裝置公共根目錄:
//輸出:/storage/emulated/0
Log.d("DaMai",Environment.getExternalStorageDirectory().getPath());
複製程式碼
Environment.getExternalStoragePublicDirectory
File Environment.getExternalStoragePublicDirectory(String type)
我們可以通過type訪問公有目錄下對應的檔案,例如:
//輸出:/storage/emulated/0/Music
Log.d("DaMai",Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getPath());
複製程式碼
Environment物件為我們提供了豐富的訪問對應公有目錄下的type,我們可以通過Environment物件原始碼進行檢視,這裡不再贅述。
Environment.getExternalStorageState
String Environment.getExternalStorageState() 獲得外部儲存SD卡的狀態,在讀寫SD卡的時候,我們應該先判斷一下SD卡的狀態,是否能夠支援讀寫。
具體返回值及對應的狀態也可以檢視Environment.getExternalStorageState的原始碼。
私有目錄
是否需要使用者許可權:4.4以上不需要
是否能被其他應用訪問:否
解除安裝應用資料是否被刪除:是
私有目錄,在Android4.4系統以上。不需要註冊和使用者授權SD讀寫的許可權,就可以在應用的私有目錄進行讀寫檔案。並且檔案不能被其他應用所訪問,具有較好的隱私性和安全性,並且在使用者刪除的時候,對應的應用私有目錄也會被刪除。
私有目錄地址:/storage/emulated/0/Android/data/應用包名
相關API
私有目錄下訪問的API都在ContextWrapper物件上。這意味這我們可以直接在Activity中呼叫或者通過Context物件去呼叫。
getExternalCacheDir
File Context.getExternalCacheDir() 訪問/storage/emulated/0/Android/data/應用包名/cache目錄,該目錄用來存放應用的快取檔案,當我們通過應用刪除快取檔案的時候,該目錄下的檔案會被清除。
//輸出:/storage/emulated/0/Android/data/com.example.vicky.yinji/cache
Log.d("DaMai",this.getExternalCacheDir().getPath());
複製程式碼
getExternalFilesDir
File Context.getExternalFilesDir(String type) 訪問/storage/emulated/0/Android/data/應用包名/files 目錄,該目錄用來存放應用的資料,當我們通過應用去清除應用資料的時候,該目錄下的檔案會被清除。我們也可以通過type,去建立並獲得對應目錄下的File檔案。例如:
//建立並輸出:/storage/emulated/0/Android/data/com.example.vicky.yinji/files/test
Log.d("DaMai",this.getExternalFilesDir("test").getPath());
複製程式碼
我們也可以將type傳為null,這時候訪問的目錄就是files目錄,例如:
//輸出:/storage/emulated/0/Android/data/com.example.vicky.yinji/files
Log.d("DaMai",this.getExternalFilesDir(null).getPath());
複製程式碼
覆盤
我們開發中經常會進行檔案儲存,這次我們終於弄清楚了Android的檔案儲存,當我們需要儲存一些私密性和安全性比較高的小資料,例如使用者的賬號密碼等資訊,我們可以存放在內部儲存空間上;當我們需要存放一些能夠被其他應用也能訪問的資料,並且當應用被刪除的時候,不希望資料被清除的時候,我們可以放到外部儲存的公有目錄下,但別忘了申請讀寫SD卡的許可權哦;當我們需要存放一些應用的資料和快取資料,希望有較好的隱私性和應用被刪除的時候,對應的應用資料和快取也被刪除,這時候我們可以選擇存放在外部儲存的私有目錄下。
我是大麥,如果喜歡我的文章,請給我一顆小心心。