關于Android的File存儲,這裡先說下Java中的File類,根據面向對象的思想,Java中對檔案的操作也進行了對象的封裝,這個操作檔案的類就是File類,File提供了豐富的api來進行檔案的操作,比如常見的createNewFile(),mkdir(),mkdirs(),exists(),isFile(),isDictory(),renameto(),delete(),getName(),getPath()....方法比較多,讀者可以自行通過api文檔檢視,同樣這一套的檔案操作在Android中也适用。
下面對幾個常用的api進行說明舉例。
File構造函數
/**
*這裡通過将給定路徑名字元串轉換為抽象路徑名來建立一個新File執行個體。
*然後執行file.createNewFile();如果該檔案存在,則建立失敗,不存在則建立,傳回一個boolean值
*/
File file=new File(String pathname);
/**
*這裡根據parent抽象路徑名和child路徑名字元串建立一個新File執行個體。
*執行file.createNewFile();如果parent抽象路徑名不存在,或者檔案已經建立過,依然不能建立成功。
*/
File file=new File(File parent,String child);
/**
*根據 parent 路徑名字元串和 child 路徑名字元串建立一個新 File 執行個體。
*執行file.createNewFile();如果parent抽象路徑名不存在,或者檔案已經建立過,依然不能建立成功。
*/
File file=new File(String parentpath,String child);
File常用方法
- createNewFile();如果檔案已經存在,則建立失敗,否則成功建立,還有其他可能
- mkdir();建立檔案夾,注意:如果建立目标檔案夾的父級目錄不存在,就會建立失敗
- mkdirs();建立多級目錄,父級檔案目錄不存在的話,會自動建立父級目錄。
- isFile();判斷是否是一個檔案
- isDictory();判斷是否是一個檔案夾
- delete();删除檔案或者檔案夾,注意要是删除檔案夾的時候,檔案夾裡還有檔案或者檔案夾,則不能删除,意思是隻能删除一個空檔案夾。
- exists();判斷檔案或者檔案夾是否存在
- getName();擷取檔案或者檔案夾的名稱
- getPath();擷取相對路徑
- getAbsolutePath();擷取絕對路徑
- length();擷取檔案或者檔案夾的長度
Android中的File存儲
- 在介紹如何在Android平台下進行檔案的讀取之前,有必要了解Android平台下的資料存儲規則。在其他的作業系統如Windows 平台下,應用程式可以自由地或者在特定的通路權限基礎上通路或修改其他應用程式名下的檔案等資源,而在Android平台下,一個應用程式中所有的資料都是私有的。
- 當應用程式被安裝到系統中後,其所在的包會有一個檔案夾用于存放自己的資料,隻有這個應用程式才有對這個檔案夾的寫入權限,這個私有的檔案夾位于Android系統的/data/data/<應用程式包名>目錄下,其他的應用程式都無法再這個檔案夾中寫入資料。除了存放私有的資料檔案夾外,應用程式也具有SD卡的寫入權限。
- 使用檔案I/O 方法可以直接往手機中存儲資料,預設情況下這些檔案不可以被其他的應用程式通路。Android平台支援 java平台下的 檔案I/O操作, 主要使用FileInputStream 和 FileOutputStream 這兩個類來實作檔案的存儲與讀取。擷取這兩個類對象的方式有兩種。
- 第一種方式就是像Java平台下的實作方式一樣通過構造器直接建立,如果需要向打開的檔案末尾寫入資料,可以通過使用構造器FileOutputStream(File file, boolean append)将 append設定為true來實作。不過需要注意的是采用這種方式獲得FileOutputStream 對象時如果檔案不存在或不可寫入時,會抛出 FileNotFoundException 異常。
- 第二種擷取 FileInputStream 和 FileOutputStream 對象的方式是調用 Context.openFileInput 和 Context.openFileOutput兩個方法來建立。
方法說明
-
- openFileInput(String filename) 打開應用程式私有目錄下的的指定私有檔案以讀入資料,傳回一個FileInputStream 對象,如果該檔案不存在,依然會發生異常,FileNotFoundException
- openFileOutput(String fileName,int mode) 打開應用程式私有目錄下的的指定私有檔案以寫入資料,傳回一個FileOutputStream 對象,如果檔案不存在就建立這個檔案。
除了這兩個方法外,Context對象還提供了其他幾個用于對檔案操作的方法,如下所示
- fileList() 搜尋應用程式私有檔案夾下的私有檔案,傳回所有檔案名的String數組
- deleteFile(String fileName) 删除指定檔案名的檔案,成功傳回true,失敗傳回false
在使用openFileOutput方法打開檔案以寫入資料時,需要指定打開模式。預設為零,即MODE_PRIVATE。不同的模式對應的的含義如下:
常量 含義
MODE_PRIVATE
預設模式,檔案隻可以被調用該方法的應用程式通路
MODE_APPEND
如果檔案已存在就向該檔案的末尾繼續寫入資料,而不是覆寫原來的資料。
MODE_WORLD_READABLE
賦予所有的應用程式對該檔案讀的權限。
MODE_WORLD_WRITEABLE
賦予所有的應用程式對該檔案寫的權限。
但是Android 4.2開始,Android不推薦使用,MODE_WORLD_READABLE ,MODE_WORLD_WRITEABLE 這兩種模式。
App在手機上儲存檔案或者緩存資料時,應該遵守以下幾點:
- 不要随意占用使用者的内置存儲。
- 不要随意在SD卡上建立目錄,應該放置自己應用包名對應的擴充存儲目錄下,解除安裝App時可以被自動清除。
- 對占用的磁盤空間有上限,并按照一定的政策進行清除。
Android下有哪些檔案目錄
應用私有存儲(内置存儲)
擷取方式:
Context.getFileDir():擷取内置存儲下的檔案目錄,可以用來儲存不能公開給其他應用的一些敏感資料如使用者個人資訊
Context.getCacheDir():擷取内置存儲下的緩存目錄,可以用來儲存一些緩存檔案如圖檔,當内置存儲的空間不足時将系統自動被清除
絕對路徑:
Context.getFileDir():/data/data/應用包名/files/
Context.getCacheDir():/data/data/應用包名/cache/
寫權限:不需要申請
這是手機的内置存儲,沒有root的過的手機是無法用檔案管理器之類的工具檢視的。而且這些資料也會随着使用者解除安裝App而被一起删除。這兩個目錄其實就對應着設定->應用->你的App->存儲空間下面的清除資料和清楚如下圖所示
應用擴充存儲(SD卡)
擷取方式:
Context.getExternalFilesDir():擷取SD卡上的檔案目錄
Context.getExternalCacheDir():擷取SD卡上的緩存目錄
絕對路徑:
Context.getExternalFilesDir():SDCard/Android/data/應用包名/files/
Context.getExternalCacheDir():SDCard/Android/data/應用包名/cache/
寫權限:
API < 19:需要申請
API >= 19:不需要申請
既然是SD卡上的目錄,那麼是可以被其他的應用讀取到的,是以這個目錄下,不應該存放使用者的敏感資訊。同上面一樣的,這裡的檔案會随着App解除安裝而被删除,也可以由使用者手動在設定界面裡面清除。
公共存儲(SD卡)
擷取方式:Environment.getExternalStorageDirectory()
絕對路徑:SDCard/你設定的檔案夾名字/
寫權限:需要申請
如果我們的App需要存儲一些公共的檔案,甚至希望下載下傳下來的檔案即使在我們的App被删除之後,還可以被其他App使用,那麼就可以使用這個目錄。這個目錄是始終需要申請SD寫入權限的。
Android6.0下應該把檔案放到哪裡?
根據最開始提到的規則,其實如果僅僅是做了簡單的圖檔緩存工作,那麼我們應該把圖檔緩存放到/data/data/應用包名/cache/或者SDCard/Android/data/應用包名/cache/,因為在6.0系統(API23)時,不需要申請權限就可以向這兩個目錄寫入檔案。而且/data/data/應用包名/cache/目錄,是内置存儲的應用私有緩存目錄,在系統空間不夠時還會被自動清除,對于圖檔緩存來講也是一個不錯的管理政策,不過谷歌建議我們最好還是自己實作緩存清除管理,例如用DiskLruCache。
參考文章:http://unclechen.github.io/2016/03/06/Android6.0%E6%9D%83%E9%99%90%E9%80%82%E9%85%8D%E4%B9%8BSD%E5%8D%A1%E5%86%99%E5%85%A5/