Android 資料儲存---File內部儲存
Java提供了一套完整的IO流體系,包括FileInputStream、FileOutputStream等,通過這些IO流可以非常方便的訪問磁碟上的內容。Android同樣支援以這種方式來訪問手機儲存器上的檔案。
Context提供瞭如下兩種方法來開啟應用程式的資料資料夾裡的檔案IO流。
- FileInputStream openFileInput(String name):開啟應用程式的資料資料夾下的name檔案對應的輸入流。
- FileOutputStream openFileOutput(String name,int mode):開啟應用程式的資料資料夾下的name檔案對應的輸入流。
以上兩個方法預設開啟的檔案路徑為:/data/data/< package name>/files目錄下的name檔案。即應用程式的資料資料夾是/data/data/< package name>/files,故此時File儲存的資料位於內部儲存器上。
上面兩種方法分別用於開啟檔案輸入流、輸出流,其中第二個引數mode指定開啟檔案的模,該模式支援如下值:
- MODE_PRIVATE引數:指示要建立這個檔案(或者,如果有同名檔案存在,則會替換舊檔案),並且讓這個檔案是應用程式的私有檔案。
- MODE_APPEND:如果檔案已經存在,則在後面追加資料
- MODE_WORLD_READABLE:讓其他應用有讀的許可權
- MODE_WORLD_WRITEABLE:讓其他應用有寫的許可權
注:MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE已經在Android 4.2(API level 17)廢棄了,因為這樣危險,安全性不高。
1.往內部儲存內寫檔案(寫入到/data/data/com.xxx.xxx/files目錄下,com.xxx.xxx為應用程式包名):
String FILE_NAME = "hello_file";
String FILE_TEXT = "hello world!!!";
FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE _PRIVATE);
fos.write(FILE_TEXT.getBytes());
fos.close();
執行上面程式碼,發現/data/data/com.xxx.xxx/files目錄下多了個hello_file檔案。
2.讀取內部儲存內的檔案(也就是從/data/data/com.xxx.xxx/files目錄下讀取檔案):
String FILE_NAME = "hello_file";
byte[] b = new byte[1024];
StringBuffer sb = new StringBuffer();
FileInputStream fis = openFileInput(FILE_NAME);
int num;
while ((num = fis.read(b)) != -1) {
sb.append(new String(b, 0, num));
}
fis.close();
Log.d("xxx", sb.toString());
執行一下,成功列印hello world!!!
除此之外,Context還提供瞭如下幾個方法來訪問應用程式的資料資料夾。
- getDir(String name,int mode):在應用程式資料資料夾下獲取或建立name對應的子目錄。
- File getFileDir():獲取應用程式的資料資料夾的絕對路徑。
- String[] fileList():返回應用程式資料資料夾下的全部檔案。
- deleteFile(String name):刪除應用程式資料資料夾下的制定檔案。
下面示範如何讀取應用程式資料資料夾得內容。給程式介面佈局只有兩個文字框和兩個按鈕,其中第一組文字框和按鈕用於處理寫入,文字框用於接收使用者輸入,當用戶單擊”寫入”按鈕時,程式會把文字框中的資料寫入檔案;第二組文字框和按鈕用於處理讀取,當用戶點選“讀取”按鈕時,該文字框顯示檔案中的資料,效果如下:
程式碼如下:
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:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/writeEditText"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/writeButton"
android:text="Write File"
android:textAllCaps="false"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/readButton"
android:text="Read File"
android:textAllCaps="false"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/readEditText"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
final String FILE_NAME = "file.test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println(new StringBuffer("a").append("b").append("c"));
Button writeButton = (Button) findViewById(R.id.writeButton);
Button readButton = (Button) findViewById(R.id.readButton);
final EditText writeEditText = (EditText) findViewById(R.id.writeEditText);
final EditText readEditText = (EditText) findViewById(R.id.readEditText);
Log.i("FILE",getFilesDir().toString());
writeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
write(writeEditText.getText().toString());
writeEditText.setText("");
}
});
readButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
readEditText.setText(read());
}
});
}
private String read() {
try {
//從檔案讀取資料
FileInputStream fileInputStream = openFileInput(FILE_NAME);
byte[] buffer = new byte[1024];
int hasRead = 0;
StringBuilder stringBuilder = new StringBuilder("");
while ((hasRead = fileInputStream.read(buffer)) > 0 )
{
stringBuilder.append(new String(buffer,0,hasRead));
}
fileInputStream.close();
return stringBuilder.toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private void write(String s) {
try {
//向檔案寫入資料
FileOutputStream fileOutputStream = openFileOutput(FILE_NAME,MODE_APPEND);
PrintStream printStream = new PrintStream(fileOutputStream);
printStream.println(s);
printStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
3.在記憶體儲存內儲存快取檔案(也就是將資料儲存在/data/data/< package name>/cache目錄下的檔案中)
如果只是要快取一些資料,而不是要持久的儲存它,那麼應該使用getCacheDir()方法來開啟一個File物件,它代表了應用程式要儲存臨時快取檔案的內部目錄。
當裝置的內部儲存空間不足的時候,Android可能會刪除這些快取檔案來回收儲存空間。但是,不應該依賴系統來給你清理這些檔案,應該始終自己來維護快取檔案,並且要把儲存空間的耗費限定在合理的範圍內,如1MB。當用戶解除安裝應用程式時,這些檔案會被刪除。
getCacheDir():獲取應用程式的快取目錄資料夾,即/data/data/< package name>/cache目錄。
將上面的Demo改為嚮應用程式的快取目錄下下程式只需:
//向檔案寫入資料:
FileOutputStream fileOutputStream = openFileOutput(FILE_NAME,MODE_APPEND);
改為:
FileOutputStream fileOutputStream =
new FileOutputStream(getCacheDir()+ File.separator+FILE_NAME);
//從檔案讀取資料:
FileInputStream fileInputStream = openFileInput(FILE_NAME);
改為:
FileInputStream fileInputStream =
new FileInputStream(getCacheDir()+ File.separator+FILE_NAME);
注:
- openFileOutput()和openFileInput()函式屬於Android中定義的函式,檔案預設儲存的路徑為/data/data/< package name>/files目錄下。
- new FileOutputStream()和new FileInputStream()函式屬於Java中定義的函式,沒有預設的檔案儲存路徑,故需要制定檔案路徑。