由於項目須要,最近學了不少數據本地持久化的知識。有不少情景咱們都須要遇到文件存儲:從保存用戶的登陸狀態到記錄瀏覽信息,從保存圖片到下載大型文件。因此有必要了解下Android的文件存儲系統,從而輕鬆地去管理咱們應用日常產生的數據。java
這是按存儲的位置來分的。應用對內部存儲操做不須要任何的權限,這就意味着不須要在AndroidManifest.xml
裏聲明權限,也不須要在Android6.0上進行權限適配。其實作過權限適配同窗都清楚,只有外部存儲的權限:Manifest.permission.READ_EXTERNAL_STORAGE
和Manifest.permission.WRITE_EXTERNAL_STORAGE
。我的理解:權限是爲了系統保證應用安全和用戶安全而設的,既然系統對內部存儲有着最高的管理權限,應用只能在系統分配的空間存儲文件,就不必有這個內部存儲權限
了。android
咱們App在內部存儲都有本身的專有目錄: /data/data/PackageName
。存放了 WebView 緩存頁面信息,SharedPreferences 和 數據庫數據等。不過沒root的是看不到的.固然咱們能夠經過Android Studio主界面右下處的Device File Exploer
來查看:web
建立一個新應用,包名:com.renny.storage
,系統在內部存儲默認建立了三個空文件夾,經過Context來獲取下:數據庫
File getFilesDir()
:返回內部存儲的Files文件夾File getCacheDir()
:返回內部存儲的cache文件夾File getCodeCacheDir()
:返回內部存儲的code_cache文件夾,要求Android5.0+File getDataDir()
: 返回內部存儲的根文件夾,要求Android7.0+一般咱們將文件存放在的Files文件夾,經過fileList()
能夠獲取該文件夾下的所有文件的文件名。openFileInput()
和 openFileOutput()
方法也是在該目錄下操做文件。這些方法都是Context裏的,在activity中能夠直接調用。舉個例子:緩存
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try{
FileOutputStream outputStream = openFileOutput("hello.text", Context.MODE_PRIVATE);
outputStream.write( "Hello world!".getBytes());
outputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
String[] files = fileList();
for (String file : files) {
Log.d("file--",file);
}
}
複製代碼
這樣就會在Files文件夾下面生成一個hello.text
文件了,打印出的信息就是 hello.text
。安全
上面僅僅是一個全新應用預先建立的內部存儲目錄。其餘相關的子目錄以下(使用時建立):cookie
/data/data/PackageName/shared_prefs/
:
用來存儲 SharedPreference,相關函數爲:getSharedPreferences(String fileName, int mode);
app
/data/data/PackageName/databases/
ide
用來存儲數據庫文件,相關函數: getDatabasePath()
;函數
/data/data/PackageName/app_webview
/data/data/PackageName/xxxwebviewcachexxx
存儲應用內置 webview 所產生的 cache 和 cookies 等,該目錄因爲 android 版本不一樣名字和位置也可能不一樣;
/data/data/PackageName/lib
用來存儲該應用的 .so 靜態庫文件;
內部存儲空間較小,由於只對應用自己可見,適合保存一些私密信息,好比登陸信息,須要加密的數據等等,當一個應用卸載以後,內部存儲中的這些文件也會被刪除。另外內部存儲的文件讀取速度通常也是高於外部存儲的。
外部存儲空間就很是大了,你們買的手機32Gb,64Gb容量,還有還有XXGb的SD卡,都是外部存儲。外部存儲能夠直接在手機的文件管理應用中瀏覽。外部存儲中的文件是能夠被用戶或者其餘應用程序修改的(系統無論了),因此讀寫也須要Manifest.permission.READ_EXTERNAL_STORAGE
和Manifest.permission.WRITE_EXTERNAL_STORAGE
權限,來讓用戶本身管理。 有了權限,外部存儲的全部目錄咱們都能訪問到。 好比根目錄: Environment.getExternalStorageDirectory()
下面咱們按照存儲內容的用途來介紹:
Environment.getExternalStoragePublicDirectory(int type)
根據type會返回對應的文件目錄。這些文件目錄就是用來存放全部App均可能會用到的一些文件。type有不少種,好比: Environment.DIRECTORY_DCIM
,獲得的就是外部存儲根文件夾下的DCIM文件夾,也就是手機存儲照片的地方。經常使用的還有:
Environment.DIRECTORY_DOWNLOADS
Download文件夾Environment.DIRECTORY_MUSIC
Music文件夾Environment.DIRECTORY_MOVIES
Movies文件夾等等等等。通常把須要和其餘應用共享的文件均可以放這裏(不過狀況好像不是不少)。
雖然在外部存儲管不了應用在哪存取文件,但也不能任由應用胡亂在任何位置存文件,並且這些文件在應用卸載了之後也要刪除吧,否則到後來外部存儲全是卸載後應用留下的垃圾文件。因此Android有個目錄用來專門給應用存文件(固然想不想在那存,系統管不了)。目錄結構相似於內部存儲:
/storage/emulated/0/Android/data/PackageName/
方法也和內部存儲很相似:
Context.getExternalFilesDir(String type)
:Android/data/PackageName/files文件夾
Context.getExternalCacheDir()
:Android/data/PackageName/cache文件夾 上面的type和Environment.getExternalStoragePublicDirectory(int type)
用法是相似的,有一點不一樣:
能夠爲空:getContext().getExternalFilesDir(null)
:此時就是files根文件夾 Android/data/packageName/files
;
也能夠傳一個值: getContext().getExternalFilesDir("apple")
:此時就是files文件夾下的子文件夾:Android/data/packageName/files/apple
。
state = Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
//todo
}
複製代碼