1. 程式人生 > >Android 的檔案儲存

Android 的檔案儲存

選擇記憶體儲還是外儲存 所有安卓裝置都有兩個儲存區域,記憶體儲和外儲存。以前的安卓裝置都有提供一個內建的儲存(記憶體儲),和一個可插拔的儲存(外儲存),例如SD卡。但是現在的許多裝置是不支援外接儲存卡的,而是把內建的儲存分成兩個區域,相當於記憶體儲和儲存。所以不管裝置是否支援外接儲存卡,它都有記憶體儲和外儲存這兩個區域。儲存操作相關API的呼叫是一樣的。以下是記憶體儲和外儲存的區別: 記憶體儲:
  • 一直可用
  • 預設情況下,儲存於此的檔案只有該應用本身有許可權操作。
  • 當用戶解除安裝該應用,系統會刪除該應用儲存在記憶體儲的所有檔案。
如果你不想使用者和其他應用操作你的檔案,最好的方式就是儲存在記憶體儲。 外儲存:
  • 並非一直可用,比如當用戶用資料線連線電腦並開啟資料儲存或者移除儲存卡。
  • 對使用者和其他應用可讀。
  • 當用戶解除安裝該應用時必不會刪除儲存在外儲存的檔案,除非你儲存的時候呼叫的是.
如果你要儲存的檔案對操作許可權沒有要求,比如和其他應用共享或者允許使用者操作,那麼最好的方式就是儲存在外儲存。

Tip: 預設情況下應用是安裝在記憶體儲,但是你可以在manifest中指定android:installLocation的屬性值讓應用安裝在外儲存上。特別是當應用應用特別大,而使用者又有足夠的問儲存空間時。更多詳情,請查閱App Install Location

獲得外儲存許可權

<manifest
...><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ... </manifest>

Caution:目前,所有應用不必宣告相關許可權就可以在外儲存上執行讀的操作。然而,不久的將來就需要了。如果你的應用需要讀取的操作(不需要寫的操作),你可以在manifest中宣告許可權,這樣可以保證應用在後續版本中正常執行(即使當前系統並不要求該許可權)

<manifest ...><uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"
/> ... </manifest>

You don’t need any permissions to save files on the internal storage. Your application always has permission to read and write files in its internal storage directory.對於記憶體儲並不需要任何讀寫的許可權。

在記憶體儲中儲存檔案

當要在記憶體儲儲存檔案時,可以通過以下兩種方式獲取合適的儲存位置:
返回一個分配給該應用的記憶體儲資料夾。
返回一個分配給該應用的記憶體儲快取資料夾File物件。當快取檔案不再需要時記得刪除掉。當系統儲存不夠用時,系統可能會刪除掉快取的檔案且沒有提示。
要在以上任一種資料夾中建立檔案時,可以用File(dir, fileName)構造方法,第一個引數傳入以上其中一種方法返回的記憶體儲資料夾物件:
File file =newFile(context.getFilesDir(), filename);
String filename ="myfile";Stringstring="Hello world!";FileOutputStream outputStream;try{
  outputStream = openFileOutput(filename,Context.MODE_PRIVATE);
  outputStream.write(string.getBytes());
  outputStream.close();}catch(Exception e){
  e.printStackTrace();}
或者說,你需要快取檔案,你可以使用createTempFile()。例如以下的示例從一個URL中提取出檔名,再用這個檔名建立一個儲存在快取資料夾中的檔案:
publicFile getTempFile(Context context,String url){File file;try{String fileName =Uri.parse(url).getLastPathSegment();
        file =File.createTempFile(fileName,null, context.getCacheDir());catch(IOException e){// Error while creating file}return file;}

Note:一個應用的記憶體儲空間是由應用包名標示的在安卓檔案系統中的一個特定區域,技術上來講,如果把檔案的mode設為可讀,那麼其他應用就可訪問。但是,前提是其他應用必須預先知道你的應用的包名和要訪問的檔名。除非你明確宣告某個檔案為可讀或可寫,否則其他應用無法訪問你的記憶體儲檔案也沒有讀寫的許可權。

在外儲存中儲存檔案

因為外儲存有可能是不可用的,比如當用戶開啟USB資料儲存或者是解除安裝提供外儲存的SD卡時,所以每當你要使用外儲存是最好先核實下外儲存是否可用。你可以通過呼叫getExternalStorageState()來查詢外儲存的狀態。如果返回的狀態是MEDIA_MOUNTED,那麼表示你可以讀寫外儲存。例如,以下兩個非常實用的方法可以用來確定外儲存的可用性:
/* Checks if external storage is available for read and write確定問儲存是否可讀寫 */publicboolean isExternalStorageWritable(){String state =Environment.getExternalStorageState();if(Environment.MEDIA_MOUNTED.equals(state)){returntrue;}returnfalse;}/* Checks if external storage is available to at least read 確定外儲存是都至少可讀*/publicboolean isExternalStorageReadable(){String state =Environment.getExternalStorageState();if(Environment.MEDIA_MOUNTED.equals(state)||Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){returntrue;}returnfalse;}
雖然說整個外儲存對於使用者和所有應用都是可操作的,但是有兩種型別的檔案你可能會儲存在這裡:

公開檔案

對其他應用和使用者開放的檔案應該儲存在這裡,當用戶解除安裝你的應用時,這些檔案應該保留。比如你的應用拍攝的圖片或下載的檔案。 私有檔案

完全屬於你的應用的檔案並且在使用者解除安裝你的應用時應該被刪除的檔案可以儲存在這裡。雖然技術上來說,儲存在外儲存的檔案對於使用者和其他應用都可以訪問,但是這些檔案對於使用者和其他應用一文不值。當用戶刪除你的應用時,系統會自動刪除你的應用儲存在這裡的所有檔案。比如說你的應用下載的資原始檔或臨時的檔案。

publicFile getAlbumStorageDir(String albumName){// Get the directory for the user's public pictures directory. File file =newFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), albumName);if(!file.mkdirs()){Log.e(LOG_TAG,"Directory not created");}return file;}
如果你想儲存應用私有的檔案,可以呼叫getExternalFilesDir()來獲取相應的資料夾,並在第一個引數指定你想要的型別。每個用這個方式建立的資料夾都是放在一個父資料夾裡,這個父資料夾存裡放著所有當使用者解除安裝該應用時系統會自動刪除的檔案。 例如,以下的方法用來建立一個存放照片的資料夾:
publicFile getAlbumStorageDir(Context context,String albumName){// Get the directory for the app's private pictures directory. File file =newFile(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), albumName);if(!file.mkdirs()){Log.e(LOG_TAG,"Directory not created");}return file;}
如果沒有一個系統預定義的型別子資料夾的名字適合你要儲存的檔案,你也可以在呼叫getExternalFilesDir()方法時第一個引數傳null,這樣返回的是在外儲存中分配給你的應用的私有資料夾根目錄。 要記住,儲存在由getExternalFilesDir()返回的資料夾中的檔案,當用戶解除安裝你的應用時,這些檔案全部會被刪除。如果你想要使用者刪除你的應用後還保留這些檔案,最好是使用getExternalStoragePublicDirectory()方法。比如說你的應用是個相機應用,當解除安裝該應用時使用者還想保留所拍的照片。

查詢剩餘儲存空間

但是,系統並不保證你通過getFreeSpace()查詢出來有多少剩餘儲存就可以儲存多少。如果剩餘儲存容量比你要儲存的檔案大小大個幾MB,那麼一般可以成功儲存。

Note:其實你也可以不用在儲存檔案前預先查詢剩餘多少儲存空間,你可以嘗試著直接寫入資料,然後如果有出現異常直接捕獲就行了。這種寫法一般可以用在當你事先不知道要寫入資料的大小的時候。比如說當你要儲存一張PNG格式的圖片前要先把他轉化為JPEG格式,那麼你就不知道要儲存的資料的大小。

刪除檔案

你應該經常刪除不再需要的檔案,最直接的方法就是直接呼叫File物件的delete()方法。

myFile.delete();

如果要刪除的檔案是儲存在記憶體儲中,你可以通過呼叫Conext的deleteFile()方法來刪除。

myContext.deleteFile(fileName);

Note:當用戶解除安裝你的應用時,安卓系統會自動刪除以下位置的檔案:

然而你應該制定一個規則定期刪除記憶體儲快取資料夾中的快取檔案和其他你不再需要的檔案。