在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 讀取文件
當然了,該實例只是提供了使用存儲文件和讀取文件的方法來實現記事本的一種思路,實例本身還有許多需要完善的地方。