Android Internal and External storage 讀寫檔案

Android storage

Android可以將檔案儲存在手機上的記憶體(Internal Storage),或是外部儲存媒體 SDcard(External Storage)。
Internal storage 是儲存在 /data/data/package_name/files 目錄中,每個 App 會有一個獨立的目錄來儲存檔案,其他 App 無法存取。由於是儲存在手機的記憶體中,所有會有空間的限制,不建議在這裡儲存容量太大的檔案。使用 Internal storage 不需要額外設定權限。

使用 External Storage 則必須設定讀取 SDcard 的權限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
儲存目錄為 /sdcard,容量則取決於 SDcard 本身的容量。儲存在 Internal storage 時,當 App 被移除,所有的資料也會被移除,而 External storage 因為是儲存在 SDcard,所以不會因為 App 被移除而消失。

使用方法

兩者使用方式基本上都相同,只是在讀寫時會使用不同的類別。

Internal storage:

//讀檔
FileInputStream fin = this.openFileInput(filename);
//寫檔
FileOutputStream fout = this.openFileOutput(filename, Context.MODE_PRIVATE);
對Internal storage做讀寫時是使用 android.content.ContextWrapper 類別中的方法,this 是指該 Activity。Context.MODE_PRIVATE 是指該檔案為私有的,只能由該 App 讀寫。另外還有其他指示性的常數,在 Context 抽象類別可以找到以 MODE_ 開頭的常數。

External storage:

//取得外部儲存媒體的目錄(這裡會是/sdcard)
String path = Environment.getExternalStorageDirectory().getPath();
//檔案路徑,記得要加斜線(這樣/sdcard/filename)
File file = new File(path + "/" + filename);
//讀檔
FileInputStream fin = new FileInputStream(file);
//寫檔
FileOutputStream fout = new FileOutputStream(file);
基本上就是使用原本的 Java.io 裡的類別。這樣檔案會直接儲存在 SDcard 下,或許你會想要建立一個自己 App 使用的目錄,使用的方式如下:
//先取得sdcard目錄
String path = Environment.getExternalStorageDirectory().getPath();
//利用File來設定目錄的名稱(myappdir)
File dir = new File(path + "/myappdir");
//先檢查該目錄是否存在
if (!dir.exists()){
    //若不存在則建立它
    dir.mkdir();
}
如此就會有一個 /sdcard/myappdir 的目錄產生。之後你的檔案就可以放在
File file = new File(path + "/myappdir/" + filename);
此外,在使用 External storage 之前,最好先檢查一下外部媒是否存在及能否讀寫。
//取得外部儲存媒體的狀態
String state = Environment.getExternalStorageState();
//判斷狀態
if (Environment.MEDIA_MOUNTED.equals(state)) {
   Log.d(TAG, "可以讀寫");
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
   Log.d(TAG, "只可以讀取,無法寫入");
} else {
   Log.d(TAG, "無法讀寫");
}

程式碼

我把實際使用的程式碼寫成方法,方便使用,請依自己的需求修改,如下:

Internal storage:

//寫檔
private void writeDataToFile(String filename, String data){
  try {
    FileOutputStream fout = this.openFileOutput(filename, Context.MODE_PRIVATE);
    fout.write(data.getBytes());
    fout.close();
  } catch (FileNotFoundException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
}

//讀檔
private String readDataFromFile(String filename){
  String result = null;
  try {
    StringBuilder sb = new StringBuilder();
    FileInputStream fin = this.openFileInput(filename);
    byte[] data = new byte[fin.available()];
    while (fin.read(data) != -1) {
      sb.append(new String(data));
    }
    fin.close();
    result = sb.toString();
  } catch (FileNotFoundException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
return result;
}

External storage:

//寫檔到sdcard
private void writeToSDcard(String filename, String data){
   //建立自己的目錄
   String path = Environment.getExternalStorageDirectory().getPath();
   File dir = new File(path + "/movietime");
   if (!dir.exists()){
     dir.mkdir();
   }

   try {
       File file = new File(path + "/movietime/" + filename);
       FileOutputStream fout = new FileOutputStream(file);
       fout.write(data.getBytes());
       fout.close();
   } catch (FileNotFoundException e) {
       e.printStackTrace();
   } catch (IOException e) {
       e.printStackTrace();
   }
   Log.d(TAG, "Write to SDCARD!");
}

//從sdcard讀檔
private String readFromSDcard(String filename){
    String path = Environment.getExternalStorageDirectory().getPath();
    File file = new File(path + "/movietime/" + filename);
    StringBuilder sb = new StringBuilder();
    try {
        FileInputStream fin = new FileInputStream(file);
        byte[] data = new byte[fin.available()];
        while (fin.read(data) != -1) {
            sb.append(new String(data));
        }
        fin.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.d("TAG", "Read from SDCARD: " + json.toString());
    return sb.toString();
}
本文網址:http://blog.tonycube.com/2012/03/android-internal-and-external-storage.html
Tony Blog 撰寫,轉載時請註明出處及文章連結,謝謝 😀

我要留言

留言小提醒:
1.回覆時間通常在晚上,如果太忙可能要等幾天。
2.請先瀏覽一下其他人的留言,也許有人問過同樣的問題。
3.程式碼請先將它編碼後再貼上。(線上編碼:http://bit.ly/1DL6yog)
4.文字請加上標點符號及斷行,難以閱讀者恕難回覆。
5.感謝您的留言,您的問題也可能幫助到其他有相同問題的人。