在Android中一共提供了5種資料存放區方式,分別為:
(1)Files:通過FileInputStream和FileOutputStream對檔案進行操作。
(2)Shared Preferences:常用來儲存索引值對形式的資料,對系統配置資訊進行儲存。
(3)Content Providers:資料共用,用於應用程式之間資料的訪問。
(4)SQLite:Android內建的輕量級關係型資料庫,支援SQL語言,用來儲存大量的資料,並且能夠對資料進行使用、更新、維護等操作。
(5)Network:通過網路來儲存和擷取資料。
本篇博文主要介紹第一種方式,通過檔案儲存體資料。
在Android中,所建立的用於儲存資料的檔案可以位於兩個位置:裝置本身的儲存空間中,或是外接的存放裝置中(SD卡)。無論儲存在哪個位置,在預設的情況下,該檔案都是不能夠供不同的應用程式共用的。
下面分別介紹如何將檔案儲存體在裝置本身的儲存空間中以及外接的存放裝置中。
1.將檔案儲存體在裝置本身的儲存空間中
在Android中,可以使用Context類提供的以下兩個方法來實現檔案儲存體。
(1)public abstract FileInputStream openFileInput(String name);//開啟檔案輸入資料流
(2)public abstract FileOutStream openFileOutput(String name, int mode);//開啟檔案輸出資料流
其中,openFileInput()方法表示開啟檔案輸入資料流,用於從檔案中讀取資料;openFileOutput()方法表示開啟檔案輸出資料流,用於向檔案中寫入內容。
此外,openFileOutput()方法中的第二個參數mode用於指定檔案的操作模式,其可選值有以下4種:
(1)Context.MODE_APPEND;//內容追加模式。在該模式下,系統會檢查檔案是否存在,如果存在,則將內容追加到檔案的末尾,如果檔案不存在,則建立該檔案並寫入內容。
(2)Context.MODE_PRIVATE;//預設操作模式。在該模式下,檔案作為私人資料,只能被該應用程式本身訪問。並且,在該模式下,寫入的內容會覆蓋原檔案的內容。
(3)Context.MODE_WORLD_READABLE;//可讀模式。在該模式下,別的應用程式可以讀取該檔案內容。
(4)Context.MODE_WORLD_WRITEABLE;//可寫入模式。在該模式下,別的應用程式可以將內容寫入該檔案。
1.1隱藏檔
一個簡單的隱藏檔的例子如下:
1 /* 2 * Function : 儲存檔案到本地記憶體中 3 * Author : 部落格園-依舊淡然 4 */ 5 public void saveContentToLocal(String fileNmae, String content) throws IOException { 6 FileOutputStream fileOutputStream = mContext.openFileOutput(fileNmae, Context.MODE_APPEND); 7 fileOutputStream.write(content.getBytes()); 8 if(fileOutputStream != null) { 9 fileOutputStream.close();10 }11 }
以上的代碼,通過將openFileOutput()的第二個參數設定為MODE_APPEND,指定了以內容追加模式隱藏檔。
1.2單體測試
如何來驗證以上代碼的正確性呢?我們可以通過建立單體測試來快速的對以上代碼進行驗證。
具體的單體測試代碼如下:
1 /*2 * Function : 單體測試儲存檔案到本地3 * Author : 部落格園-依舊淡然4 */5 public void saveFileToLocal() throws IOException {6 Context cotext = getContext();7 FileService fileService = new FileService(cotext);8 fileService.saveContentToLocal("test.txt", "部落格園-依舊淡然");9 }
通過運行該單體測試,我們在本地建立了一個名為“test.txt”的文字檔,其內容為“部落格園-依舊淡然”。
該檔案究竟被存放到了什麼地方呢?其實,每安裝一個應用程式,在data/data目錄下都會產生一個檔案夾,用來儲存該應用程式的資料。1所示。
圖1 Files方式儲存資料到本地的檔案目錄
可見,該檔案被存放到了目錄data/data/com.example.android_datastorage_files/files下,其中com.example.android_datastorage_files是該工程的包名。匯出該“test.txt”文字檔,開啟可以看見其中內容確實是“部落格園-依舊淡然”。
1.3讀取檔案
那麼又該如何在程式中讀取該檔案呢?下面的代碼給出了一種實現方案。
1 /* 2 * Function : 從本地記憶體中讀取檔案 3 * Author : 部落格園-依舊淡然 4 */ 5 public String getFileFromLocal(String fileNmae) throws IOException { 6 7 FileInputStream fileInputStream = mContext.openFileInput(fileNmae); 8 9 //建立ByteArrayOutputStream對象,用於儲存FileInputStream對象中的資料10 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();11 12 //迴圈讀寫FileInputStream對象內容並儲存到ByteArrayOutputStream對象中13 int len = 0;14 byte[] data = new byte[1024];15 while((len = fileInputStream.read(data)) != -1) { 16 byteArrayOutputStream.write(data, 0, len);17 }18 19 if(fileInputStream != null) { //關閉FileInputStream對象20 fileInputStream.close();21 }22 23 return new String(byteArrayOutputStream.toByteArray());24 }
同樣的,我們可以建立一個單體測試來快速驗證其正確性。具體方法和上一個單體測試類別似,這裡就不再贅述了。
2.將檔案儲存體在外接存放裝置中(SD卡)
通常,手機的記憶體是極其有限的,更普遍的做法是將檔案儲存體到SD卡中。
將檔案儲存體在外接存放裝置中的方法和將檔案儲存體在裝置本身的儲存空間中的方法類似,唯一的區別是每次向SD卡中儲存以及從SD卡中讀取檔案時,都需要檢測SD卡的狀態。
2.1檢測SD卡的狀態
在Android中,檢測SD卡的狀態需要使用到Environment類。通過使用該類的getExternalStorageState()方法可以獲得外接存放裝置(SD卡)的狀態。其中,外接存放裝置的狀態有九種,具體2所示。
圖2 外接存放裝置狀態
其中,MEDIA_MOUNTED表示外接存放裝置可讀可寫。
2.2隱藏檔
隱藏檔到SD卡中的一個簡單例子如下:
1 /* 2 * Function : 儲存檔案到SD卡中 3 * Author : 部落格園-依舊淡然 4 */ 5 public boolean saveContentToSDCard(String fileNmae, String content) throws IOException { 6 7 boolean isExternalStorageAvailable = false; //SD卡可讀寫的標誌位 8 FileOutputStream fileOutputStream = null; //FileOutputStream對象 9 10 //建立File對象,以SD卡所在的路徑作為檔案儲存體路徑11 File file = new File(Environment.getExternalStorageDirectory(), fileNmae); 12 13 //判斷SD卡是否可讀寫14 if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {15 isExternalStorageAvailable = true;16 fileOutputStream = new FileOutputStream(file); //建立FileOutputStream對象17 fileOutputStream.write(content.getBytes()); //向FileOutputStream對象中寫入資料18 if(fileOutputStream != null) { //關閉FileOutputStream對象19 fileOutputStream.close();20 }21 }22 return isExternalStorageAvailable;23 }
其中,Environment.getExternalStorageDirectory()方法用於擷取SD卡所在的路徑。在建立File對象時,指定其儲存路徑為SD卡所在的路徑,既可以將檔案儲存體到SD卡中。
2.3單體測試
同樣地,我們建立一個單體測試來對以上的代碼進行驗證。
具體的單體測試代碼如下:
1 /* 2 * Function : 單體測試儲存檔案到SD卡中 3 * Author : 部落格園-依舊淡然 4 */ 5 public void saveFileToSDCard() throws IOException { 6 Context cotext = getContext(); 7 FileService fileService = new FileService(cotext); 8 boolean flag = fileService.saveContentToSDCard("hello.txt", "部落格園-依舊淡然"); 9 Log.i(TAG, "flag-->"+flag);10 }
通過運行該單體測試,我們可以在SD卡中建立了一個名為“hello.txt”的文字檔,其內容為“部落格園-依舊淡然”。
那麼,該檔案又儲存在什麼地方呢?答案是mnt/sdcard目錄下,3所示。
圖3 Files方式儲存資料到SD卡中的檔案目錄
2.4讀取檔案
從SD卡中讀取檔案與從本地記憶體中讀取檔案的方法大致相同,這裡就不再贅述了。
有一點需要說明,因為程式中用到讀寫SD卡,所以需要在AndroidManifest.xml檔案中加入向SD卡中寫入資料的許可權和在SD卡中建立和刪除檔案的許可權。具體實現方法如下:
1 <!-- 向SD卡中寫入資料的許可權 -->2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />3 <!-- 在SD卡中建立和刪除檔案的許可權 -->4 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
3.執行個體(記事本)
瞭解了在Android中隱藏檔和讀取檔案的方法,我們可以實現一個簡單的記事本應用程式。
通過使用該記事本可以輸入檔案的名字和內容,點擊“儲存檔案”可以將檔案內容儲存到SD卡中,4所示。
圖4 儲存檔案
當需要讀取檔案時,可以點擊“讀取檔案”按鈕。此時,會將檔案內容從SD卡中的對應檔案中讀取並顯示出來。5所示。
圖5 讀取檔案
當然了,該執行個體只是提供了使用隱藏檔和讀取檔案的方法來實現記事本的一種思路,執行個體本身還有許多需要完善的地方。