文件存儲
文件存儲是 Android 中最基本的一種數據存儲方式, 它不對存儲的內容進行任何的格式化處理, 所有數據都是原封不動地保存到文件當中的, 因而它比較適合用於存儲一些簡單的文本數據或二進制數據。 如果你想使用文件存儲的方式來保存一些較爲複雜的文本數據, 就需要定義一套自己的格式規範,這樣方便於之後將數據從文件中重新解析出來。
將數據存儲到文件中
Context 類中提供了一個 openFileOutput ()方法,可以用於將數據存儲到指定的文件中。這個方法接收兩個參數, 第一個參數是文件名, 在文件創建的時候使用的就是這個名稱, 注意這裏指定的文件名不可以包含路徑,因爲所有的文件都是默認存儲到/data/data/packagename/files/ 目 錄 下 的 。 第 二 個 參 數 是 文 件 的 操 作 模 式 , 主 要 有 兩 種 模 式 可 選 ,MODE_PRIVATE 和 MODE_APPEND。
其實文件的操作模式本來還有另外兩種, MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE, 這兩種模式表示允許其他的應用程序對我們程序中的文件進行讀寫操作, 不過由於這兩種模式過於危險,很容易引起應用的安全性漏洞,現已在 Android 4.2 版本中被廢棄。
openFileOutput ()方法返回的是一個 FileOutputStream 對象, 得到了這個對象之後就可以使用 Java 流的方式將數據寫入到文件中了。以下是一段簡單的代碼示例,展示瞭如何將一段文本內容保存到文件中:
public void save(){
String data="data is saved!"
FileOutputStream out=null;
BufferedWriter writer=null;
try{
out=openFileOutput("data",Context.MODE_PRIVATE);
writer=new BufferedWriter(new OutputStreamWriter(out));
writer.write(data);
}catch(IOException){
e.printStackTrace;
}finally{
try{
if(writer!=null){
writer.close();
}
}catch(IOException e){
e.printStackTrace;
}
}
}
這裏通 過openFileOutput() 方法能夠得到一個 FileOutputStream 對象,然後再借助它構建出一 個OutputStreamWriter 對象,接着再使用 OutputStreamWriter 構建出一個 BufferedWriter 對象,這樣你就可以通過 BufferedWriter 來將文本內容寫入到文件中了。
在安卓開發中如何實現對數據保存到文件呢?
下面我們就編寫一個完整的例子, 藉此學習一下如何在 Android 項目中使用文件存儲的技術。 首先創建一個 FileSaved 項目 , 並修改 activity_main.xml 中的代碼, 如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Type something here" />
</LinearLayout>
這裏只是在佈局中加入了一個 EditText,用於輸入文本內容。其實現在你就可以運行一下程序了, 界面上肯定會有一個文本輸入框。 然後在文本輸入框中隨意輸入點什麼內容, 再按下 Back 鍵,這時輸入的內容肯定就已經丟失了,因爲它只是瞬時數據,在活動被銷燬後就會被回收。而這裏我們要做的,就是在數據被回收之前,將它存儲到文件當中。修改MainActivity 中的代碼,如下所示:
public class MainActivity extends Activity {
private EditText inputEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inputEdit = (EditText) findViewById(R.id.edit);
}
@Override
protected void onDestroy() {
super.onDestroy();
String inputText = inputEdit.getText().toString();
save(inputText);
}
private void save(String inputText) {
FileOutputStream out=null;
BufferedWriter writer=null;
try {
out=openFileOutput("data", Context.MODE_PRIVATE);
writer=new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
首先在 onCreate()方法中獲取了 EditText 的實例, 然後重寫了 onDestroy()方法, 這樣就可以保證在活動銷燬之前一定會調用這個方法。 在 onDestroy()方法中我們獲取了 EditText 中輸入的內容, 並調用 save()方法把輸入的內容存儲到文件中, 文件命名爲 data。現在重新運行一下程序,並在 Editext 中輸入一些內容,如圖所示:
然後按下 Back 鍵關閉程序,這時輸入的內容就已經保存到文件了。那麼如何才能證實數據確實已經保存成功了呢?可以藉助 DDMS 的 File Explorer 來查看一下。 切換到 DDMS 視 圖 , 並 點 擊 File Explorer 切 換 卡 , 在 這 裏 進 入 到 /data/data/com.example.shijj.filesaved/files/目錄下,可以看到生成了一個 data 文件,如圖所示。
然後點擊圖中最左邊的按鈕可以將這個文件導出到電腦上。
使用EditPlus打開這個文件,裏面的內容如圖所示。
這樣就證實了,在 EditText 中輸入的內容確實已經成功保存到文件中了。不過只是成功將數據保存下來還不夠,還需要想辦法在下次啓動程序的時候讓這些數據能夠還原到 EditText 中,因此接下來我就要展示如何從文件中讀取數據。
如何實現對數據從文件中的讀取
類似於將數據存儲到文件中, Context 類中還提供了一個 openFileInput()方法, 用於從文件中讀取數據。這個方法要比 openFileOutput()簡單一些,它只接收一個參數,即要讀取的文件名,然後系統會自動到/data/data/package name/files/目錄下去加載這個文件,並返回一個FileInputStream 對象,得到了這個對象之後再通過 Java 流的方式就可以將數據讀取出來了。
以下是一段簡單的代碼示例,展示瞭如何從文件中讀取文本數據:
private String load() {
FileInputStream fis = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try {
fis = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(fis));
String line = "";
while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return content.toString();
}
首先通過 openFileInput()方法獲取到了一個 FileInputStream 對象,然後藉助它又構建出了一個 InputStreamReader 對象,接着再使用 InputStreamReader 構建出一個BufferedReader 對象,這樣就可以通過 BufferedReader 進行一行地讀取,把文件中所有的文本內容全部讀取出來並存放在一個 StringBuilder 對象中, 最後將讀取到的內容返回就可以了。
瞭解了從文件中讀取數據的方法,就可以重新完善一下剛剛寫的demo, 使得重新啓動程序時 EditText中能夠保留我們上次輸入的內容。 修改 MainActivity中的代碼, 如下所示:
public class MainActivity extends Activity {
private EditText inputEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inputEdit = (EditText) findViewById(R.id.edit);
String inputText = load();
if (!TextUtils.isEmpty(inputText)) {
inputEdit.setText(inputText);
inputEdit.setSelection(inputText.length());
Toast.makeText(MainActivity.this, "Restoring Successed", Toast.LENGTH_SHORT).show();
}
}
private String load() {
FileInputStream fis = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try {
fis = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(fis));
String line = "";
while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return content.toString();
}
這裏的思路非常簡單, 在 onCreate()方法中調用 load()方法來讀取文件中存儲的文本內容, 如果讀到的內容不爲空, 就調用 EditText 的 setText()方法將內容填充到 EditText裏,並調用 setSelection 方法將輸入光標移動到文本的末尾位置以便於繼續輸入,然後彈出一句還原成功的提示。 load()方法中的細節我們前面已經講過了。
注意上述代碼在對字符串進行非空判斷的時候使用了 TextUtils.isEmpty()方法,這是一個非常好用的方法, 它可以一次性進行兩種空值的判斷。 當傳入的字符串等於 null 或者等於空字符串的時候, 這個方法都會返回 true, 從而使得我們不需要單獨去判斷這兩種空值, 再使用邏輯運算符連接起來了。現在重新運行一下程序,剛纔保存的 Content 字符串肯定會被填充到 EditText 中,然後編寫一點其他的內容, 比如在 EditText 中輸入 diaomao, 接着按下 Back 鍵退出程序, 再重新啓動程序,這時剛纔輸入的內容並不會丟失,而是還原到了 EditText 中,如圖 所示:
到這裏文件存儲方面的基本內容已經涵蓋的差不多了,其實所用到的核心技術就是 Context類中提供的 openFileInput()和 openFileOutput()方法, 之後就是利用 Java 的各種流來進行讀寫操作就可以了。