Android應用程序私有目錄下文件操作總結

每一個Android程序都有一個特有的,只能由本程序自己訪問的私有目錄,這個目錄一般位於/data/data/<Package Name>/目錄下。所有應用程序私有目錄中保存的文件在用戶卸載該應用的時候,都會被自動刪除掉。

在Android應用程序開發中,經常使用的一些系統提供的API,會在這個私有目錄中創建一些子目錄,並將相應的數據存放於其中。而這些對於應用程序開發者來說,完全是透明的,本文將對所有會訪問應用程序私有目錄的API及其行爲做一個簡單的總結。

程序私有目錄下,一般會有下面幾個子目錄,它們的用處和涉及到的API(多半繼承自Context類)如下:

一、files目錄

這個目錄是用來存放應用程序自己在安裝過後創建的文件的地方。有下面幾個API都會涉及對這個目錄的操作:

File Context.getFilesDir();

該方法返回指向/data/data/<Package Name>/files/目錄的一個File對象。

FileInputStream Context.openFileInput(String name);

該方法將在/data/data/<Package Name>/files/目錄下打開一個指定名字的文件,這個文件只能用來讀取,不能用來寫入。函數將返回一個FileInputStream類的實例。

FileOutputStream Context.openFileOutput(String name, int mode);

該方法將在/data/data/<Package Name>/files/目錄下打開一個指定名字的文件,這個文件可以用來寫入。如果這個文件不存在,會新創建一個。函數將返回一個FileOutputStream類的實例。

這個函數的參數除了文件名之外,還有一個所謂的模式(mode)。它主要用來指定創建文件的讀寫權限以及當文件已經存在時,如何寫入文件。主要有下面幾個值:

1)  MODE_PRIVATE(0x00000000),表示創建的文件只能被本程序或者共享同一用戶ID的其它應用程序訪問到,別的程序既沒有權限讀也沒有權限寫,這個是默認模式;

2)  MODE_WORLD_READABLE(0x00000001),表示創建的文件可以被任何程序讀,但是不能修改;

3)  MODE_WORLD_WRITABLE(0x00000002),表示任何程序都可以修改創建文件的內容,出於對安全方面的考慮,從Android 4.2.2(API Level 17)開始,這種模式已經被捨棄了;

4)  MODE_APPEND(0x00008000),表示如果要寫入的文件已經存在了,則將寫入的內容追加到文件末尾,而不是覆蓋原來的內容。

如果想聯合使用以上的多個模式,可以用“+”將它們聯接起來。

如果想查看/data/data/<Package Name>/files/目錄下到底有哪些文件,可以用下面的函數:

String[] Context.fileList();

該函數將返回包含/data/data/<Package Name>/files/目錄下所有現存文件文件名的字符串數組。

如果想刪除一個在/data/data/<Package Name>/files/目錄下的文件,可以用下面的函數:

boolean Context.deleteFile(String name);

如果指定名字的文件被刪除成功將返回true,反之返回false。

二、cache目錄

這個目錄是默認用來給應用程序做數據緩存的,在程序中可以通過下面的API獲得這個目錄的路徑:

File Context.getCacheDir();

該方法返回指向/data/data/<Package Name>/cache/目錄的一個File對象。

當內部存儲空間變得緊張的時候,存於該目錄下的所有文件都有可能被Android系統自動刪除掉。

三、databases目錄

該目錄主要用來存放應用程序自己創建或使用的SQL Lite數據庫文件。有下面幾個API都會涉及對這個目錄的操作:

SQLiteDatabase Context.openOrCreateDatabase(String name, int mode, CursorFactory factory);

該函數將在/data/data/<Package Name>/databases/目錄下,查找指定名字的數據庫文件,如果沒有的話,會創建一個新的。創建數據庫的時候,也需要指定模式,有如下幾種:

1)MODE_PRIVATE(0x00000000),作用和前面介紹的相同;

2)MODE_WORLD_READABLE(0x00000001),作用和前面介紹的相同;

3)MODE_WORLD_WRITABLE(0x00000002),作用和前面介紹的相同;

4)MODE_ENABLE_WRITE_AHEAD_LOGGING(0x00000008),這個模式是從Android3.0(API Level 11)開始加入進來的。將打開數據庫的預寫日誌功能,提高數據的可靠性。

同時,從Android 4.0(API Level 15)開始,還提供了一個android.database.sqlite.SQLiteOpenHelper抽象類來幫助操作SQL Lite數據庫。一般用法是自己實現一個類,並繼承自SQLiteOpenHelper類,重載onCreate(數據庫第一次被創建)、onUpgrade(數據庫升級)和onOpen(數據庫被打開)方法,加入自己的邏輯。接着構造出一個你自己實現類的實例,並調用下面的函數,打開或創建出數據庫:


 
  1. SQLiteDatabase SQLiteOpenHelper.getReadableDatabase();

  2. SQLiteDatabase SQLiteOpenHelper.getWritableDatabase();

前面的函數獲得的數據庫只能用來讀,而後面的函數獲得的數據庫既可以讀也可以寫。

其實,這個幫助類最終也是通過調用了前面的Context. openOrCreateDatabase函數來打開或創建數據庫,並且是使用默認的MODE_PRIVATE模式。因此,通過SQLiteOpenHelper類,最終也是在/data/data/<Package Name>/databases/目錄下創建了數據庫文件,並且別的程序不能訪問到。

File Context.getDatabasePath(String name);

該方法將返回一個指向指定數據庫文件的File對象。

如果想查看/data/data/<Package Name>/ databases/目錄下到底有哪些數據庫,可以用下面的函數:

String[] Context.databaseList();

該函數將返回包含/data/data/<Package Name>/databases/目錄下所有數據庫名的字符串數組。

如果想刪除一個在/data/data/<Package Name>/databases/目錄下的數據庫,可以用下面的函數:

boolean Context.deleteDatabase(String name);

如果指定名字的數據庫文件被刪除成功將返回true,反之返回false。

四、shared_prefs目錄

該目錄主要用來存放應用程序自己創建或使用的一些常用配置文件(Shared Preference)。

程序中主要是用下面的函數來獲取一個配置文件:

SharedPreferences Context.getSharedPreferences(String name, int mode);

函數的第一個參數是配置文件的名字,函數調用成功之後會在/data/data/<Package Name>/shared_prefs/目錄下創建一個名字爲<name>.xml的文件。

函數的第二個參數是創建的模式,有下面幾個值:

1)MODE_PRIVATE(0x00000000),作用和前面介紹的相同;

2)MODE_WORLD_READABLE(0x00000001),作用和前面介紹的相同;

3)MODE_WORLD_WRITABLE(0x00000002),作用和前面介紹的相同;

4)MODE_MULTI_PROCESS(0x00000004),如果你的應用程序有多個進程,並且都需要操作同一個配置文件的話,出於數據同步方面的考慮,在每次修改之前都需要檢查一下這個配置文件是否已經被別的進程修改了。

五、lib目錄

這個子目錄存放着的是應用程序需要使用的Native原生程序,即JNI調用需要加載的.so文件。

這些文件一般是位於apk安裝包裏的lib目錄下。在程序安裝的時候,系統會將所有apk文件中lib目錄下的所有原生程序拷貝到這個子目錄下。

該目錄是程序不能操作的,不能在程序運行時,向該目錄拷貝.so文件,然後再通過調用System.loadLibrary函數將其加載進來。

六、自定義目錄

當然,程序也可以在自己的私有目錄中創建任意名字的子目錄:

File Context.getDir(String name, int mode);

該方法返回指向/data/data/<Package Name>/下指定名稱的文件夾的一個File對象。如果該文件夾不存在則用指定名稱創建一個新的文件夾。

該目錄下還有一些其它的目錄,如app_sslcache、app_webview等,這些都是有Android系統中的某些特殊模塊自動創建的,一般可以通過其名字猜到是由哪個模塊創建的。

例子:

在files目錄下創建文件夾111和文件aaa:

int myProcessID = Process.myPid();//import android.os.Process
File filepath = MainActivity.this.getFilesDir();//this.getCacheDir();
String filepathstr = filepath.toString();
Log.d(TAG, "filepathstr= "+filepath.toString());//打印的是:filepathstr= /data/user/0/com.example.myapplication/files
//創建文件夾 111
File f = new File(filepathstr, "111");
Log.d(TAG, "fpathstr= "+f.toString());//fpathstr= /data/user/0/com.example.myapplication/files/111
Log.d(TAG, "f.getAbsolutePath= "+f.getAbsolutePath());//f.getAbsolutePath= /data/user/0/com.example.myapplication/files/111
//以上兩個方法獲取的path是一樣的
try {

//下面這行代碼打印結果  f.getAbsolutePath= /data/data/com.example.myapplication/files/111
    Log.d(TAG, "f.getAbsolutePath= "+f.getCanonicalPath());
} catch (IOException e) {
    e.printStackTrace();
}
if(!f.exists()){
    Log.e(TAG, "onCreate: !f.exists()");
    f.mkdirs();//創建文件夾
}
else if(f.exists()) {
    Log.e(TAG, "onCreate: f.exists()");
}
//創建文件 aaa
File f2 = new File(filepathstr, "aaa");
try {
    f2.createNewFile();//創建文件
    //file.mkdirs();
    Log.d(TAG, "onClick: file.createNewFile()");
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章