Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android官方開發文檔Training系列課程中文版:數據存儲之文件存儲

Android官方開發文檔Training系列課程中文版:數據存儲之文件存儲

編輯:關於android開發

Android官方開發文檔Training系列課程中文版:數據存儲之文件存儲


Android使用的文件系統和其它平台的磁碟式文件系統很相似。這節課描述了如何通過FileAPI在Android文件系統上進行讀取文件和寫入文件的操作。

一個File對象適合被用來按照從頭到尾的方式讀取或寫入大量的數據,它不適合被用來跳躍式訪問,也就是隨機訪問。舉個例子,這對圖片文件或者任何基於網絡的數據交換是非常適合的。

這節課展示了如何執行APP中最基本的文件相關任務。這節課假定你有Linux的文件系統基礎以及Java標准的輸入輸出基礎。

選擇內部或外部存儲器

所有的Android設備有兩個文件存儲分區:”internal”和”external”分區。這些名詞來自於較早的Android版本,當大多數的設備提供了內置的固定內存,會添加一個可移除的存儲器媒體比如micro SD卡(外部存儲器)。一些設備固定的存儲器空間劃分為”internal”和”external”分區,所以甚至是沒有可移除的存儲媒體,那麼仍然還是會有兩個存儲器空間。API會表現出相同的行為,無論外部存儲器是不是可移除的。下面是對每個存儲器空間的事實總結。

Internal storage:

它總是可用的。 默認情況下APP將文件保存在這裡,只允許該APP可以訪問。 如果用戶卸載了你的APP,那麼系統會將APP的所有文件從這裡移除。

如果你不想讓用戶或者其它APP訪問你文件的話,內部存儲器是一個合適的地方。

External storage:

它並不總是可用的,因為用戶可能將外部存儲掛載為USB存儲器,和另外一些可能會被從設備上移除的情況。 它是全局可訪問的,所以如果文件存儲在這裡,它可能會你的控制范圍之外被訪問。 當用戶卸載了你的APP,系統只會刪除你在getExternalFilesDir()返回目錄中保存的文件。

如果不需要訪問限制的話,外部存儲器是一個合適的地方,它可以另其它的APP訪問你的文件,用戶也可以通過電腦訪問這些文件。

Note:盡管APP安裝的時候會默認被安裝在內部存儲器內,不過你可以在清單文件中通過指定android:installLocation屬性來指定應用安裝的位置。如果APK的尺寸很大,並且外部存儲空間比內部存儲空間大的話,用戶會很欣賞這點。更多相關信息,請參見: App Install Location。

獲取外部存儲器的權限

如果要在外部存儲器寫入文件,你必須在清單文件中請求WRITE_EXTERNAL_STORAGE權限。


    
    ...

警告:目前所有的APP都有能力訪問外部存儲器而不需要指定權限。然而,這會在未來的發行版做更改。如果你的APP需要讀取外部存儲器的數據(不是寫入),那麼你需要聲明READ_EXTERNAL_STORAGE權限,來確保你的APP還可以在未來的版本中繼續工作,在更改生效之前,你應該現在就聲明這項權限。


     android:name="android.permission.READ_EXTERNAL_STORAGE" />
    ...

然而,如果你的APP使用了WRITE_EXTERNAL_STORAGE權限,那麼它會隱性的含有讀取外部存儲器的權限。

你在內部存儲器中保存文件不要任何權限。你的應用程序總是有權讀取和寫入文件到內部存儲器目錄。

保存文件到內部存儲器

當要保存文件到內部存儲器時,你可以通過下面兩個方法中的一個獲得一個合適的目錄對象File:

getFilesDir() 返回一個代表APP的內部存儲器目錄的File對象。

getCacheDir() 返回一個File對象,這個對象代表了APP在內部存儲器中的臨時文件緩存目錄。為了確保文件不再需要的時候可以刪除到它,應該在任何給定時間內對內存的數量實現一個合理的尺寸限制,比如1MB。如果系統開始在存儲器上緩慢運行,那麼可能會刪除你的臨時文件,而不會有任何警告。

為了在這些目錄中創建一個文件,你可以使用File()的構造方法,傳遞一個上面的方法目錄到File的構造方法中,來指定內部存儲器目錄。就像這樣:

File file = new File(context.getFilesDir(), filename);

或者,你可以調用openFileOutput()獲得一個FileOutputStream對象來將文件寫入到內部存儲器中。這是一個如何寫入一些文本到文件中的例子:

String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try {
  outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
  outputStream.write(string.getBytes());
  outputStream.close();
} catch (Exception e) {
  e.printStackTrace();
}

又或者,如果你需要緩存一些文件,你應該使用createTempFile()。舉個例子,下面這個方法從URL中提取了文件的名字,然後使用這個名字在內部緩存目錄中創建了一個文件:

public File getTempFile(Context context, String url) {
    File file;
    try {
        String fileName = Uri.parse(url).getLastPathSegment();
        file = File.createTempFile(fileName, null, context.getCacheDir());
    catch (IOException e) {
        // Error while creating file
    }
    return file;
}

**Note:**APP的內部存儲路徑是通過APP的包名特別指定的,並且被放置在Android文件系統中一個特殊的位置。技術上講,其它的APP是可以讀取你的內部文件的,如果你設置的文件模式是可讀的。然而,其它的APP也應該知道你APP的包名和文件名。其它的APP不能浏覽你的內部目錄,並且沒有訪問和寫入的權限,除非你特別設置了文件是和讀寫的。所以,一旦你對內部存儲器文件使用了MODE_PRIVATE模式,那麼其它APP永遠不可能訪問到這些文件。

保存文件到外部存儲器

因為外部存儲器有可能是不可用的,比如當用戶將它掛載到了PC上,或者將SD卡移除了,所以你應該在訪問它之前檢查它是否可用。你可以通過getExternalStorageState()方法查詢外部存儲器的狀態。如果返回的狀態等於MEDIA_MOUNTED,那麼你可以讀取和寫入文件。舉個例子,下面的方法用於檢查存儲器是否可用:

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state) ||
        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        return true;
    }
    return false;
}

盡管外部存儲器是可以被用戶或者其它APP修改的,這裡有兩種你可能會用到的文件保存類別。

Public文件:
在這種情況下,文件應該會被其它APP或者用戶隨便訪問。當用戶卸載了你的APP,那麼這些文件還會保留給用戶。

舉個例子,APP捕獲的照片或者下載的其它文件。

Private文件:
這些文件會正當的屬於你的APP,並且在用戶卸載APP的時候會刪除它們。盡管這些文件從技術上講是可以被用戶或者其它APP訪問的,因為這些文件是在外部存儲器上。實際上這些文件不會提供給APP之外的用戶。當用戶卸載了APP,那麼系統會將這些文件從外部存儲器中刪除。

舉個例子,APP下載的附加資源或者臨時的媒體文件。

如果你想在外部存儲器上保存公開的文件,使用getExternalStoragePublicDirectory()方法獲得一個代表合適目錄的File對象。這個方法攜帶的參數指定了你需要存儲的文件類型,可以使系統對其它公開文件進行邏輯上的組織,比如DIRECTORY_MUSIC或者DIRECTORY_PICTURES,分別代表的就是公共的音樂和圖片:

public File getAlbumStorageDir(String albumName) {
    // Get the directory for the user's public pictures directory. 
    File file = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), albumName);
    if (!file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}

如果你想保存私有文件,可以調用getExternalFilesDir()方法獲取合適的目錄,然後給它傳你喜歡的一個類型的目錄名稱。每一個目錄會通過這種方式創建並被添加到父目錄中,以便封裝所有在外部存儲器上的文件,當用戶卸載APP的時候會刪除它們。

下面這個方法你可使用它創建一個個人的相冊目錄:

public File getAlbumStorageDir(Context context, String albumName) {
    // Get the directory for the app's private pictures directory. 
    File file = new File(context.getExternalFilesDir(
            Environment.DIRECTORY_PICTURES), albumName);
    if (!file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}

如果對文件沒有適合的預先定義的子目錄名稱,你可以調用getExternalFilesDir()並傳入一個Null,這會返回APP在外部存儲器上私有目錄的根目錄。

記住在getExternalFilesDir()目錄中創建的目錄會隨著APP的卸載被刪除。如果你想在刪除之後仍然保留這些文件,比如你的APP是個攝像機應用,用戶希望保留下來這些照片,你應該使用getExternalStoragePublicDirectory()方法。

無論你使用的是getExternalStoragePublicDirectory()要共享文件還是使用getExternalFilesDir()保護你APP內的文件,你使用API提供的常量比如DIRECTORY_PICTURES作為目錄的名稱來說是非常重要的。這些目錄的名稱可以為系統合適的對待,舉個例子,如果文件存儲在DIRECTORY_RINGTONES的目錄中,系統媒體掃描器會將它識別為鈴聲文件,而不是音樂文件。

查詢剩余空間

如果你可以提前知道你保存的數據有多少,你可以查詢是否有足夠的空間可以使用,通過調用getFreeSpace()或者getTotalSpace()達到這一點。這些方法分別提供了當前可用空間和磁盤容量上的總空間,這些信息有助於避免填充的磁盤容量超過固定的阈值。

然而,系統不會保證你可以寫入與getFreeSpace()返回的剩余空間容量相當的數據。如果返回的數字是幾MB,大於你想存儲的數據大小,又或者系統當前使用容量少於總容量的90%,那麼現在處理可能是安全的。否則,你可能不適合寫入到存儲器中。

Note:如果你在保存文件之前不檢查剩余可用空間,你可以試著以正確的方式寫入文件,如果事件發生了,那麼可能會引起IOException異常。如果你不知道你需要的精確空間,那麼你可能就需要這麼去做。舉個例子,如果你在存儲文件之前從PNG編碼改為了JPEG編碼,你可能就不會提前知道文件的大小。

刪除文件

你應該在文件不再需要的時候將它們刪除。最直接了當的方式就是擁有一個已經打開了的文件的引用,然後調用它的delete()方法。

myFile.delete();

如果文件被存在了內部存儲器上,你也可以要求Context定位,然後調用deleteFile()方法刪除文件。

myContext.deleteFile(fileName);

Note:當用戶卸載了你的APP,Android系統會刪除以下文件:

所有保存在內部存儲器中的文件

所有保存getExternalFilesDir()目錄下的外部存儲器中的文件

無論如何,你應該定期手動刪除所有的緩存文件,即便是通過getCacheDir()方法創建的,還應該定期刪除你不再需要的其它文件。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved