快速理解Android檔案儲存路徑

丨大麥發表於2019-02-17

Android開發過程中,我們經常會需要儲存檔案,所以我們也應該整理一下這方面的相關知識,維護好使用者裝置的檔案,更需要知道內部儲存和外部儲存的區別。

本文思維導圖

先來看一下我們本章節的思維導圖,希望能夠幫助你用碎片化或者儘量短的時間,直白、深刻的瞭解本文的知識點。

快速理解Android檔案儲存路徑

內部儲存

是否需要使用者許可權:否

是否能被其他應用訪問:否

解除安裝應用資料是否被刪除:是

內部儲存控制元件不需要使用者許可權,這意味著我們不需要使用者去授權android.permission.WRITE_EXTERNAL_STORAGEandroid.permission.READ_EXTERNAL_STORAGE我們就可以讀寫該目錄下的檔案。而且該目錄下的檔案不能被其他應用訪問。這也就保證了我們應用內部儲存的檔案的安全性和隱私性,如果我們需要檢視自己應用內部的檔案,我們可以通過Android Studio的Device File Explore工具進行訪問:

快速理解Android檔案儲存路徑

我們可以訪問/data/data/應用包名,檢視自己應用下的內部儲存檔案。

快速理解Android檔案儲存路徑

/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卡的許可權哦;當我們需要存放一些應用的資料和快取資料,希望有較好的隱私性和應用被刪除的時候,對應的應用資料和快取也被刪除,這時候我們可以選擇存放在外部儲存的私有目錄下。

我是大麥,如果喜歡我的文章,請給我一顆小心心。

相關文章