1. 程式人生 > >Android 資料儲存---File內部儲存

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中定義的函式,沒有預設的檔案儲存路徑,故需要制定檔案路徑。