Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 詳解Android文件存儲

詳解Android文件存儲

編輯:關於Android編程

摘要

其實安卓文件的操作和java在pc環境下的操作並無二致,之所以需要單獨講解是因為安卓系統提供了不同於pc的訪問文件系統根路徑的api,同時對一個應用的私有文件做了統一的管理。根據我的經驗,初學者在這部分感到很容易混淆內部存儲和外部存儲兩個概念。

其實安卓文件的操作和java在pc環境下的操作並無二致,之所以需要單獨講解是因為安卓系統提供了不同於pc的訪問文件系統根路徑的api,同時對一個應用的私有文件做了統一的管理。根據我的經驗,初學者在這部分感到很容易混淆內部存儲和外部存儲兩個概念。

相對路徑和絕對路徑

在java中,關於相對路徑和絕對路徑是這樣解釋的,如果你很熟悉這部分以下灰色文字可以跳過:

絕對路徑是指書寫文件的完整路徑,例如d:\java\Hello.java,該路徑中包含文件的完整路徑d:\java以及文件的全名Hello.java。使用該路徑可以唯一的找到一個文件,不會產生歧義。但是使用絕對路徑在表示文件時,受到的限制很大,且不能在不同的操作系統下運行,因為不同操作系統下絕對路徑的表達形式存在不同。

相對路徑是指書寫文件的部分路徑,例如\test\Hello.java,該路徑中只包含文件的部分路徑\test和文件的全名Hello.java,部分路徑是指當前路徑下的子路徑,例如當前程序在d:\abc下運行,則該文件的完整路徑就是d:\abc\test。使用這種形式,可以更加通用的代表文件的位置,使得文件路徑產生一定的靈活性。

在Eclipse項目中運行程序時,當前路徑是項目的根目錄,例如工作空間存儲在d:\javaproject,當前項目名稱是Test,則當前路徑是:d:\javaproject\Test。在控制台下面運行程序時,當前路徑是class文件所在的目錄,如果class文件包含包名,則以該class文件最頂層的包名作為當前路徑。

這是java在多數操作系統中這樣操作,很顯然是要我們盡可能的使用相對路徑,但是在安卓中,其實多數情況下我們都是使用的絕對路徑。為什麼呢?注意上面說到相對路徑是以當前項目所在路徑為當前路徑,但在安卓中我們是不可能在項目所在路徑目錄下做任何操作的,因為普通java中我們的項目創建於服務器(pc也算是服務器),運行於服務器,我們當然能在服務器操作自己的文件目錄。但是安卓開發中,我們的項目一般是創建於自己工作的電腦,而運行於手機,既然apk已經運行於手機了,那項目就已經部署到手機上了,應該以apk在手機上的位置來確定相對路徑,但我們好像們沒有辦法操作這個路徑的,因為apk是在system目錄下,就算可以操作,在這個目錄下存取文件也是沒有意義的,比如我寫一個相冊程序,圖片肯定是放在外部存儲中,而如果我要保存一個應用的一些設置數據,我是放在內部存儲的data目錄下,因此其實在安卓文件管理中,我們都是在操作絕對路徑。

File類

操作一個文件(讀寫,創建文件或者目錄)是通過File類來完成的,這個操作和java中完全一致。

Internal Storage內部存儲空間

所謂的內部存儲與外部存儲,是指是否是手機內置。手機內置的存儲空間,稱為內部存儲,它是手機一旦出廠就無法改變,它也是手機的硬件指標之一,通常來講手 機內置存儲空間越大意味著手機價格會越貴(很多地方把它稱為手機內存,但我們做軟件的知道,這並不准確,內存是指手機運行時存儲程序,數據和指令的地方; 這裡應該是手機內部存儲的簡稱為內存,而並非嚴格意義上的內存)。

內部存儲空間十分有限,因而顯得可貴,所以我們要盡可能避免使用;另外,它也是系統本身和系統應用程序主要的數據存儲所在地,一旦內部存儲空間耗盡,手機 也就無法使用了。所以對於內部存儲空間,我們要盡量避免使用。上面所談到的Shared Preferences和下面要談到的SQLite數據庫也都是存儲在內部存儲空間上的。

Android本身來講是一個Linux操作系統,所以它的內部存儲空間,對於應用程序和用戶來講就是“/data/data"目錄。它與其他的(外部的 存儲)相比有著比較穩定,存儲方便,操作簡單,更加安全(因為可以控制訪問權限)等優點。而它唯一的缺點就是它比較有限,比較可貴。

雖然,可以非常容易的知道程序本身的數據所在路徑,所有的應用程序的數據路徑都是“/data/data/app-package-name/”,所有的 程序用到的數據,比如libs庫,SharedPreferences都是存放在這個路徑下面。但我們在使用的時候最好不要,或是千萬不要直接引用這個路 徑。

使用內部存儲主要有二個方式,一個是文件操作,一個是文件夾操作。無論哪種方式,Context中都提供了相應的函數來支持,使用Context不但操作 簡單方便,最重要的是Context會幫助我們管理這些文件,也可以方便幫助我們控制文件的訪問權限。先來系統的說下Context中關於文件和文件夾操 作的函數有哪些。

a. 創建一個文件,並打開成一個文件輸出流,需要提供一個String,作為文件名

FileOutputStream output = Context.openOutputFile(filename, Context.MODE_PRIVATE); 
output.write(data);// use output to write whatever you like 
output.close();

b. 同樣,想打開一個文件作為輸入的話,也是只需要提供文件名

FileInputStream input = Context.openInputFile(filename); 
input.read(); 
input.close();

c. 列出所有的已創建的文件

String[] files = Context.fileList(); 
for (String file : files) { 
Log.e(TAG, "file is " + file); 
}

d. 刪除文件,能創建就要能夠刪除,當然也會提供了刪除文件的接口,它也非常簡單,只需要提供文件名

if (Context.deleteFile(filename)) { 
Log.e(TAG, "delete file " + filename + " sucessfully“); 
} else { 
Log.e(TAG, "failed to delete file " + filename); 
}

e. 獲取文件已創建文件的路徑,它返回一個文件對象用於操作路徑

File fileDir = Context.getFileDir(); 
Log.e(TAG, "fileDir " + fileDir.getAbsolutePath();

f. 創建一個目錄,需要傳入目錄名稱,它返回 一個文件對象用到操作路徑

File workDir = Context.getDir(dirName, Context.MODE_PRIVATE); 
Log.e(TAG, "workdir " + workDir.getAbsolutePath();

g. 以File對象方式查看所創建文件,需要傳入文件名,會返回文件對象

File store = Context.getFileStreamPath(filename); 
Log.e(TAG, "store " + store.length());

h. 獲取Cache路徑,無需要傳入參數,返回文件對象

File cachedir = Context.getCacheDir(); 
Log.e(TAG, "cachedir " + cacheDir.getAbsolutePath());

總結一下文件相關操作,可以得出以下三個特點

1. 文件操作只需要向函數提供文件名,所以程序自己只需要維護文件名即可;
2. 不用自己去創建文件對象和輸入、輸出流,提供文件名就可以返回File對象或輸入輸出流

3. 對於路徑操作返回的都是文件對象。

如前所述,內部存儲空間有限,可貴,安全,穩定,所以應該用來保存比較重要的數據,比如用戶信息資料,口令秘碼等不需要與其他應用程序共享的數據。也可以 用來創建臨時文件,但一定要注意及時刪除。另外,對於內部存儲還有一個非常重要的特點,那就是在應用程序被卸載時,應用程序在內部存儲空間的文件數據將全 部被刪除。系統這樣做的原因很簡單,就是因為內部存儲很有限,它必須保證它的可用性,因為一旦添滿,系統將無法再正常工作。

External Storage外部存儲空間

再來談談手機外部存儲空間,與內部存儲空間相對,外部存儲 空間是指手機出廠的時候不存在,用戶在使用時候可以自由添加的外部存儲介質比如TS卡,SD卡等閃存儲介質。這些閃存介質由最初的空間小價格貴,到現在的 大容量價格便宜,所以幾乎每個支持外部存儲的手機上面都有大容量(大於等於2G)的閃存卡。

Android也是不例外,它完全支持外部存儲介質。其實更確切的說,它是要依賴於外部存儲卡的,因為對於Android系統,如果沒有外部存儲卡,很多 的系統應用無法使用,比如多媒體相關的應用程序無法使用。雖然Android很依賴,但是外部存儲卡也有它自身的特點,它最大的優點就是存儲空間大,基本 上你可無限制的使用,也不怎麼擔心去清除數據。就目前來看,很多程序都在使用外部存儲卡,但很少有程序去主動清理數據,所以無論你的SD卡有多大,它的可 用空間卻越來越少。與內部存儲不同的是,當程序卸載時,它在外部存儲所創建的文件數據是不會被清除的。所以清理外部存儲空間的責任丟給了用戶自己,每隔一 段時間就去查看下SD卡,發現無用數據立馬刪除。外部存儲的缺點就是不是很穩定,對於Android手機來講可以說,很不穩定,本身閃存介質就容易出問 題,SD卡處於不能正常使用的狀態十分多。

先來說說外部存儲相關的使用方法和API

a Check media availability檢查介質的可用性.

如前所述,外部存儲介質的穩定性十分的差,所以在使用之前一定要先檢查它的可用性,如果可用再去用

final String state = Environment.getExternalStorageState(); 
if (state.equals(Environment.MEDIA_MOUNTED) || state.equals(Environment.MEDIA_READ_ONLY)) {// sd card is ready to us 

b. Get the directory獲取外部存儲卡的路徑

事實上,外部存儲卡的路徑是“/mnt/sdcard",所以你直接這樣寫去訪問也能訪問的到。鑒於可讀性和可移植性的考慮,建議這樣寫:

 File sdcardDir = Environment.getExternalStorageDirectory();

c. For API 8 or greater, there are some other useful APIs helping to manager files and directories.

如果你使用API 8(Android 2.2)或者更高,那麼SDK中又多了幾個操作外部存儲文件和路徑的接口,文檔中也建議開始者更加規范的使用SD卡。比如,創建相應的目錄去存儲相應的數 據,Music,Picture,Video等。應用程序目錄也變成了"/Android/data/package-name/data"。具體的使用 可以參考文檔,這裡不重復。當然,就像編程規范一樣,這裡只是規范,你完全可以不遵守它,但出於可讀性和可移植性,還是建議按照文檔建議的去做。

下面總結一下使用時應該注意的一些和外部存儲的特點

a. 外部存儲卡不是隨時想用就能夠用的,所以一定要記得在使用之前檢查它的可用性

b. 存儲在外部存儲卡上的數據是所有應用程序都可見,用戶也可見(使用FileManager),所以安全性不是很好,雖然文檔聲稱可以在外部存儲卡上寫程序 私有數據,但貌似沒用,用FileManager仍然可以刪除或編輯文件(Market上面的FileManager功能都十分的強大,能讓用戶看到SD 卡中的所有文件,和操作能看到的文件)。

c. Android手機支持把外部存儲卡Mount至PC做為U盤,當連接數據線時,這時SD卡變成了U盤連接到了另外的操作系統中。什麼意思,就是在 Android當中雖然有的文件屬性(隱藏,私有等),到了PC上就不一定管用了,用戶在PC上可以隨意操作文件(這就是第二點中所提及的)。

d. 如果使用外部存儲卡保存數據,一定要額外做好異常處理:外部存儲卡不可用時把數據存入哪裡;可用的時候再怎麼同步數據(這是比較頭疼的地方,可行的做法就 是當SD卡不可用時不准用戶寫數據,但這用戶體驗又不是很好,但如你所知,很多應用都這麼干);你的數據被破壞了。當然常見的異常也要考慮,比如空間滿 了,無法寫入,磁盤壞道等。
我們還可以看一下常見的文件目錄:

別忘了權限

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


Log.i(TAG, "getFilesDir = " + getFilesDir()); 
Log.i(TAG, "getExternalFilesDir = " + getExternalFilesDir("exter_test").getAbsolutePath()); 
Log.i(TAG, "getDownloadCacheDirectory = " + Environment.getDownloadCacheDirectory().getAbsolutePath()); 
Log.i(TAG, "getDataDirectory = " + Environment.getDataDirectory().getAbsolutePath()); 
Log.i(TAG, "getExternalStorageDirectory = " + Environment.getExternalStorageDirectory().getAbsolutePath()); 
Log.i(TAG, "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory("pub_test"));

以上內容比較長,希望大家可以耐心閱讀,本文所述全部都是精華,關於Android文件存儲相關知識,請點擊本站了解更多。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved